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