Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix a dead store reported by infer
[simgrid.git] / examples / sthread / pthread-producer-consumer.c
1 /* Copyright (c) 2002-2023. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 /* Simple producer/consumer example with pthreads and semaphores */
7
8 #include <pthread.h>
9 #include <semaphore.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 int AmountProduced = 3; /* Amount of items produced by a producer */
16 int AmountConsumed = 3; /* Amount of items consumed by a consumer */
17 int ProducerCount  = 2; /* Amount of producer threads*/
18 int ConsumerCount  = 2; /* Amount of consumer threads*/
19 int BufferSize     = 4; /* Size of the buffer */
20
21 sem_t empty;
22 sem_t full;
23 int in  = 0;
24 int out = 0;
25 int* buffer;
26 pthread_mutex_t mutex;
27 int do_output = 1;
28
29 static void* producer(void* id)
30 {
31   for (int i = 0; i < AmountProduced; i++) {
32     sem_wait(&empty);
33     pthread_mutex_lock(&mutex);
34     buffer[in] = i;
35     if (do_output)
36       fprintf(stderr, "Producer %d: Insert Item %d at %d\n", *((int*)id), buffer[in], in);
37     in = (in + 1) % BufferSize;
38     pthread_mutex_unlock(&mutex);
39     sem_post(&full);
40   }
41   return NULL;
42 }
43 static void* consumer(void* id)
44 {
45   for (int i = 0; i < AmountConsumed; i++) {
46     sem_wait(&full);
47     pthread_mutex_lock(&mutex);
48     if (do_output) {
49       int item = buffer[out];
50       fprintf(stderr, "Consumer %d: Remove Item %d from %d\n", *((int*)id), item, out);
51     }
52     out = (out + 1) % BufferSize;
53     pthread_mutex_unlock(&mutex);
54     sem_post(&empty);
55   }
56   return NULL;
57 }
58
59 int main(int argc, char** argv)
60 {
61   int opt;
62   while ((opt = getopt(argc, argv, "c:C:p:P:q")) != -1) {
63     switch (opt) {
64       case 'q':
65         do_output = 0;
66         break;
67       case 'c':
68         AmountConsumed = atoi(optarg);
69         break;
70       case 'C':
71         ConsumerCount = atoi(optarg);
72         break;
73       case 'p':
74         AmountProduced = atoi(optarg);
75         break;
76       case 'P':
77         ProducerCount = atoi(optarg);
78         break;
79       default: /* '?' */
80         printf("unknown option: %c\n", optopt);
81         break;
82     }
83   }
84   pthread_t* pro = malloc(ProducerCount * sizeof(pthread_t));
85   pthread_t* con = malloc(ConsumerCount * sizeof(pthread_t));
86   buffer         = malloc(sizeof(int) * BufferSize);
87   pthread_mutex_init(&mutex, NULL);
88   sem_init(&empty, 0, BufferSize);
89   sem_init(&full, 0, 0);
90
91   int* ids = malloc(sizeof(int) * (ProducerCount + ConsumerCount));
92   for (int i = 0; i < ProducerCount + ConsumerCount; i++)
93     ids[i] = i + 1; // The identity of each thread (for debug messages)
94
95   for (int i = 0; i < ProducerCount; i++)
96     pthread_create(&pro[i], NULL, producer, &ids[i]);
97   for (int i = 0; i < ConsumerCount; i++)
98     pthread_create(&con[i], NULL, consumer, &ids[i]);
99
100   for (int i = 0; i < ProducerCount; i++)
101     pthread_join(pro[i], NULL);
102   for (int i = 0; i < ConsumerCount; i++)
103     pthread_join(con[i], NULL);
104
105   pthread_mutex_destroy(&mutex);
106   sem_destroy(&empty);
107   sem_destroy(&full);
108   free(pro);
109   free(con);
110   free(buffer);
111   free(ids);
112
113   return 0;
114 }