Advertisement
DanFloyd

Readers&Writers

May 21st, 2014
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.13 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <pthread.h>
  7.  
  8. /* MACROS */
  9. #define PRINT_INFO \
  10. printf("--- Type q, then press ret to exit! ---\n"); sleep(2); \
  11.  
  12. #define IS_NZERO(s,m) \
  13. if((s) != 0){perror(m); exit(err);}
  14.  
  15. #define IS_NULL(s,m) \
  16. if((s) == NULL){perror(m); exit(errno);}
  17.  
  18. #define LOCK(s) \
  19. {IS_NZERO((err=pthread_mutex_lock(&s)),("Couldn't lock"))}
  20.  
  21. #define UNLOCK(s) \
  22. {IS_NZERO((err=pthread_mutex_unlock(&s)),("Couldn't unlock"))}
  23.  
  24. #define WAIT(s,m) \
  25. {IS_NZERO((err=pthread_cond_wait(&s,&m)),("Couldn't wait"))}
  26.  
  27. #define SIGNAL(s) \
  28. {IS_NZERO((err=pthread_cond_signal(&s)),("Couldn't send signal"))}
  29.  
  30. #define BROADCAST(s) \
  31. {IS_NZERO((err=pthread_cond_broadcast(&s)),("Couldn't broadcast the signal"))}
  32.  
  33. /* TYPE DEF */
  34. typedef enum color {
  35.     NOCOLOR,
  36.     RED,
  37.     BLUE,
  38.     GREEN,
  39.     WHITE,
  40.     BLACK
  41. } color;
  42.  
  43. typedef struct node {
  44.     color clr;
  45.     struct node* next;
  46. } node;
  47.  
  48. /* GLOBAL VAR */
  49. static node* head = NULL;
  50. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  51. pthread_cond_t cond_r = PTHREAD_COND_INITIALIZER, cond_w = PTHREAD_COND_INITIALIZER;
  52. static int working_r = 0, working_w = 0, waiting_r = 0, waiting_w = 0;
  53.  
  54. /* FUNCTION DEF */
  55. void* writer(void* args);
  56. void* reader(void* args);
  57. char* getColorName(color clr);
  58. void gcollector();
  59. static void cleanup_handler(void* arg);
  60.  
  61. /* FUNCTION IMP*/
  62. int main(){
  63.  
  64.     char ctrl;
  65.     int err = 0, status = 0;
  66.     pthread_t tid_wr0 = NULL, tid_wr1 = NULL;
  67.     pthread_t tid_re0 = NULL, tid_re1 = NULL, tid_re2 = NULL, tid_re3 = NULL, tid_re4 = NULL;
  68.  
  69.     PRINT_INFO;
  70.  
  71.     /* Creating writers's threads */
  72.     IS_NZERO((err = pthread_create(&tid_wr0, NULL, &writer, (void*)0)),"Couldn't create writer no. 0");
  73.     IS_NZERO((err = pthread_create(&tid_wr1, NULL, &writer, (void*)1)),"Couldn't create writer no. 1");
  74.  
  75.     /* Creating readers's threads */
  76.     IS_NZERO((err = pthread_create(&tid_re0, NULL, &reader, (void*) RED)),"Couldn't create the RED reader");
  77.     IS_NZERO((err = pthread_create(&tid_re1, NULL, &reader, (void*) BLUE)),"Couldn't create the BLUE reader");
  78.     IS_NZERO((err = pthread_create(&tid_re2, NULL, &reader, (void*) GREEN)),"Couldn't create the GREEN reader");
  79.     IS_NZERO((err = pthread_create(&tid_re3, NULL, &reader, (void*) WHITE)),"Couldn't create the WHITE reader");
  80.     IS_NZERO((err = pthread_create(&tid_re4, NULL, &reader, (void*) BLACK)),"Couldn't create the BLACK reader");
  81.    
  82.     /* Exit condition */
  83.     while(ctrl != 'q'){
  84.         scanf("%c",&ctrl);
  85.         if(ctrl!='q') {PRINT_INFO;}
  86.         else{
  87.             /* Killing threads */
  88.             IS_NZERO((err = pthread_cancel(tid_wr0)),"Couldn't kill writer no. 0");
  89.             printf("[ Writer no. 0 killed ]\n");
  90.             IS_NZERO((err = pthread_cancel(tid_wr1)),"Couldn't kill writer no. 1");
  91.             printf("[ Writer no. 1 killed ]\n");
  92.             IS_NZERO((err = pthread_cancel(tid_re0)),"Couldn't kill the RED reader");
  93.             printf("[ RED reader killed ]\n");
  94.             IS_NZERO((err = pthread_cancel(tid_re1)),"Couldn't kill the BLUE reader");
  95.             printf("[ BLUE reader killed ]\n");
  96.             IS_NZERO((err = pthread_cancel(tid_re2)),"Couldn't kill the GREEN reader");
  97.             printf("[ GREEN reader killed ]\n");
  98.             IS_NZERO((err = pthread_cancel(tid_re3)),"Couldn't kill the WHITE reader");
  99.             printf("[ WHITE reader killed ]\n");
  100.             IS_NZERO((err = pthread_cancel(tid_re4)),"Couldn't kill the BLACK reader");
  101.             printf("[ BLACK reader killed ]\n");
  102.             /* Calling atexit */
  103.             IS_NZERO((err=atexit(gcollector)),"Atexit failed! Possible memory leak");
  104.             /* Waiting for dead threads */
  105.             IS_NZERO((err=pthread_join(tid_wr0,(void*)&status)),"Join with writer no. 0 failed");
  106.             IS_NZERO((err=pthread_join(tid_wr1,(void*)&status)),"Join with writer no. 1 failed");
  107.             IS_NZERO((err=pthread_join(tid_re0,(void*)&status)),"Join with RED reader failed");
  108.             IS_NZERO((err=pthread_join(tid_re1,(void*)&status)),"Join with BLUE reader failed");
  109.             IS_NZERO((err=pthread_join(tid_re2,(void*)&status)),"Join with GREEN reader failed");
  110.             IS_NZERO((err=pthread_join(tid_re3,(void*)&status)),"Join with WHITE reader failed");
  111.             IS_NZERO((err=pthread_join(tid_re4,(void*)&status)),"Join with BLACK reader failed");
  112.            
  113.         }
  114.     }
  115.  
  116.     return 0;
  117. }
  118.  
  119. void* writer(void* args){
  120.  
  121.     unsigned int seed;
  122.     int err = 0;
  123.     color new_clr;
  124.     node* new_node, *it;
  125.  
  126.     printf("[ Writer %d created]\n",(int)args);
  127.  
  128.     pthread_cleanup_push(cleanup_handler,(void*)NULL);
  129.  
  130.     while(1){
  131.  
  132.         /* Generating a new random color */
  133.         if((int)args == 0) seed = time(0) * 2;
  134.         else seed = time(0);
  135.         new_clr = rand_r(&seed)%6;
  136.  
  137.         /* Locking the mutex */
  138.         LOCK(mutex);
  139.  
  140.         /* Increasing waiting readers */
  141.         waiting_w ++;
  142.  
  143.         /* Testing and resetting var */
  144.         if((working_r)||(working_w)) WAIT(cond_w,mutex);
  145.         waiting_w --;
  146.         working_w ++;
  147.  
  148.         /* Unlocking the mutex */
  149.         UNLOCK(mutex);
  150.  
  151.         /* Creating a new node with the generated color */
  152.         IS_NULL((new_node = (node*) malloc(sizeof(node))),"Couldn't allocate new nodes");
  153.         new_node->clr = new_clr;
  154.         new_node->next = NULL;
  155.  
  156.         /* Attaching the new node to the list */
  157.         if(head != NULL){
  158.             it = head;
  159.             while(it->next != NULL) it = it->next;
  160.             it->next = new_node;
  161.         } else head = new_node;
  162.         printf("** Writer %d has done its job, attached %s to the list! **\n",(int) args, getColorName(new_clr));
  163.         sleep(2);
  164.  
  165.         /* Locking the mutex */
  166.         LOCK(mutex);
  167.    
  168.         /* Setting var */      
  169.         working_w --;
  170.  
  171.         /* Waking up all the readers or the other writer */
  172.         if(waiting_r) BROADCAST(cond_r)
  173.         else if(waiting_w) SIGNAL(cond_w)
  174.  
  175.         /* Unlocking the mutex */
  176.         UNLOCK(mutex);
  177.     }
  178.  
  179.     pthread_cleanup_pop(0);
  180.  
  181.     return (void*) 0;
  182. }
  183.  
  184. void* reader(void* args){
  185.  
  186.     char* my_clr = getColorName((color) args);
  187.     int err = 0, clr_counter = 0;
  188.     node *it;
  189.  
  190.     printf("[ %s reader created ]\n",my_clr);
  191.  
  192.     pthread_cleanup_push(cleanup_handler,(void*)NULL); 
  193.  
  194.     while(1){
  195.        
  196.         /* Resetting counter and it */
  197.         clr_counter = 0;
  198.        
  199.  
  200.         /* Locking mutex */
  201.         LOCK(mutex);
  202.  
  203.         /* Testing and setting var*/
  204.         waiting_r ++;
  205.         if((working_w)||(waiting_w)) WAIT(cond_r,mutex);
  206.         waiting_r --;
  207.         working_r ++;
  208.  
  209.         /* Unlocking mutex */
  210.         UNLOCK(mutex);
  211.  
  212.         /* Reading list */
  213.         it = head;
  214.         while(it != NULL){
  215.             if(!strcmp(getColorName(it->clr),my_clr)) clr_counter ++;
  216.             it = it->next;
  217.         }
  218.         printf("## I'm the %s reader, I've found %d hits on this run! ##\n",my_clr,clr_counter);
  219.         sleep(1);
  220.        
  221.         /* Locking the mutex */
  222.         LOCK(mutex);
  223.  
  224.         /* Testing and setting var*/
  225.         working_r --;
  226.         if((!working_r)&&(waiting_w)) SIGNAL(cond_w);
  227.  
  228.         /* Unlocking mutex */
  229.         UNLOCK(mutex);
  230.     }
  231.  
  232.     pthread_cleanup_pop(0);
  233.        
  234.     return (void*) 0;
  235. }
  236.  
  237. char* getColorName(color clr){
  238.     switch(clr){
  239.         case RED    : return "RED";
  240.             case BLUE   : return "BLUE";
  241.             case GREEN  : return "GREEN";
  242.             case WHITE  : return "WHITE";
  243.             case BLACK  : return "BLACK";
  244.         default     : return "NOCOLOR";
  245.     }
  246. }
  247.  
  248. void gcollector(){
  249.  
  250.     node* it = head;
  251.        
  252.     printf("[ Collecting some garbage... ]\n");
  253.     while(it != NULL){
  254.         it = it->next;
  255.         free(head);
  256.         head = it;
  257.     }
  258.     head = NULL;
  259.     printf("[ Bye! ]\n");
  260. }
  261.  
  262. static void cleanup_handler(void* arg){
  263.     int err=0;
  264.     printf("[ Running cleanup handler... ]\n");
  265.     UNLOCK(mutex);
  266. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement