File: pthread-producer-consumer.c

package info (click to toggle)
simgrid 4.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 39,236 kB
  • sloc: cpp: 124,918; ansic: 66,744; python: 8,560; java: 6,773; fortran: 6,079; f90: 5,123; xml: 4,587; sh: 2,194; perl: 1,436; makefile: 111; lisp: 49; javascript: 7; sed: 6
file content (114 lines) | stat: -rw-r--r-- 3,110 bytes parent folder | download | duplicates (2)
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;
}