ex2.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* The classic producer-consumer example.
  2. Illustrates mutexes and conditions.
  3. All integers between 0 and 9999 should be printed exactly twice,
  4. once to the right of the arrow and once to the left. */
  5. #include <stdio.h>
  6. #include "pthread.h"
  7. #define BUFFER_SIZE 16
  8. /* Circular buffer of integers. */
  9. struct prodcons {
  10. int buffer[BUFFER_SIZE]; /* the actual data */
  11. pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */
  12. int readpos, writepos; /* positions for reading and writing */
  13. pthread_cond_t notempty; /* signaled when buffer is not empty */
  14. pthread_cond_t notfull; /* signaled when buffer is not full */
  15. };
  16. /* Initialize a buffer */
  17. static void init(struct prodcons * b)
  18. {
  19. pthread_mutex_init(&b->lock, NULL);
  20. pthread_cond_init(&b->notempty, NULL);
  21. pthread_cond_init(&b->notfull, NULL);
  22. b->readpos = 0;
  23. b->writepos = 0;
  24. }
  25. /* Store an integer in the buffer */
  26. static void put(struct prodcons * b, int data)
  27. {
  28. pthread_mutex_lock(&b->lock);
  29. /* Wait until buffer is not full */
  30. while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
  31. pthread_cond_wait(&b->notfull, &b->lock);
  32. /* pthread_cond_wait reacquired b->lock before returning */
  33. }
  34. /* Write the data and advance write pointer */
  35. b->buffer[b->writepos] = data;
  36. b->writepos++;
  37. if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
  38. /* Signal that the buffer is now not empty */
  39. pthread_cond_signal(&b->notempty);
  40. pthread_mutex_unlock(&b->lock);
  41. }
  42. /* Read and remove an integer from the buffer */
  43. static int get(struct prodcons * b)
  44. {
  45. int data;
  46. pthread_mutex_lock(&b->lock);
  47. /* Wait until buffer is not empty */
  48. while (b->writepos == b->readpos) {
  49. pthread_cond_wait(&b->notempty, &b->lock);
  50. }
  51. /* Read the data and advance read pointer */
  52. data = b->buffer[b->readpos];
  53. b->readpos++;
  54. if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
  55. /* Signal that the buffer is now not full */
  56. pthread_cond_signal(&b->notfull);
  57. pthread_mutex_unlock(&b->lock);
  58. return data;
  59. }
  60. /* A test program: one thread inserts integers from 1 to 10000,
  61. the other reads them and prints them. */
  62. #define OVER (-1)
  63. struct prodcons buffer;
  64. static void * producer(void * data)
  65. {
  66. int n;
  67. for (n = 0; n < 10000; n++) {
  68. printf("%d --->\n", n);
  69. put(&buffer, n);
  70. }
  71. put(&buffer, OVER);
  72. return NULL;
  73. }
  74. static void * consumer(void * data)
  75. {
  76. int d;
  77. while (1) {
  78. d = get(&buffer);
  79. if (d == OVER) break;
  80. printf("---> %d\n", d);
  81. }
  82. return NULL;
  83. }
  84. int main(void)
  85. {
  86. pthread_t th_a, th_b;
  87. void * retval;
  88. init(&buffer);
  89. /* Create the threads */
  90. pthread_create(&th_a, NULL, producer, 0);
  91. pthread_create(&th_b, NULL, consumer, 0);
  92. /* Wait until producer and consumer finish. */
  93. pthread_join(th_a, &retval);
  94. pthread_join(th_b, &retval);
  95. return 0;
  96. }