ex5.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* The classic producer-consumer example, implemented with semaphores.
  2. All integers between 0 and 9999 should be printed exactly twice,
  3. once to the right of the arrow and once to the left. */
  4. #include <stdio.h>
  5. #include "pthread.h"
  6. #include "semaphore.h"
  7. #define BUFFER_SIZE 16
  8. /* Circular buffer of integers. */
  9. struct prodcons {
  10. int buffer[BUFFER_SIZE]; /* the actual data */
  11. int readpos, writepos; /* positions for reading and writing */
  12. sem_t sem_read; /* number of elements available for reading */
  13. sem_t sem_write; /* number of locations available for writing */
  14. };
  15. /* Initialize a buffer */
  16. static void init(struct prodcons * b)
  17. {
  18. sem_init(&b->sem_write, 0, BUFFER_SIZE - 1);
  19. sem_init(&b->sem_read, 0, 0);
  20. b->readpos = 0;
  21. b->writepos = 0;
  22. }
  23. /* Store an integer in the buffer */
  24. static void put(struct prodcons * b, int data)
  25. {
  26. /* Wait until buffer is not full */
  27. sem_wait(&b->sem_write);
  28. /* Write the data and advance write pointer */
  29. b->buffer[b->writepos] = data;
  30. b->writepos++;
  31. if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
  32. /* Signal that the buffer contains one more element for reading */
  33. sem_post(&b->sem_read);
  34. }
  35. /* Read and remove an integer from the buffer */
  36. static int get(struct prodcons * b)
  37. {
  38. int data;
  39. /* Wait until buffer is not empty */
  40. sem_wait(&b->sem_read);
  41. /* Read the data and advance read pointer */
  42. data = b->buffer[b->readpos];
  43. b->readpos++;
  44. if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
  45. /* Signal that the buffer has now one more location for writing */
  46. sem_post(&b->sem_write);
  47. return data;
  48. }
  49. /* A test program: one thread inserts integers from 1 to 10000,
  50. the other reads them and prints them. */
  51. #define OVER (-1)
  52. struct prodcons buffer;
  53. static void * producer(void * data)
  54. {
  55. int n;
  56. for (n = 0; n < 10000; n++) {
  57. printf("%d --->\n", n);
  58. put(&buffer, n);
  59. }
  60. put(&buffer, OVER);
  61. return NULL;
  62. }
  63. static void * consumer(void * data)
  64. {
  65. int d;
  66. while (1) {
  67. d = get(&buffer);
  68. if (d == OVER) break;
  69. printf("---> %d\n", d);
  70. }
  71. return NULL;
  72. }
  73. int main(void)
  74. {
  75. pthread_t th_a, th_b;
  76. void * retval;
  77. init(&buffer);
  78. /* Create the threads */
  79. pthread_create(&th_a, NULL, producer, 0);
  80. pthread_create(&th_b, NULL, consumer, 0);
  81. /* Wait until producer and consumer finish. */
  82. pthread_join(th_a, &retval);
  83. pthread_join(th_b, &retval);
  84. return 0;
  85. }