Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- /* MACROS */
- #define PRINT_INFO \
- printf("--- Type q, then press ret to exit! ---\n"); sleep(2); \
- #define IS_NZERO(s,m) \
- if((s) != 0){perror(m); exit(err);}
- #define IS_NULL(s,m) \
- if((s) == NULL){perror(m); exit(errno);}
- #define LOCK(s) \
- {IS_NZERO((err=pthread_mutex_lock(&s)),("Couldn't lock"))}
- #define UNLOCK(s) \
- {IS_NZERO((err=pthread_mutex_unlock(&s)),("Couldn't unlock"))}
- #define WAIT(s,m) \
- {IS_NZERO((err=pthread_cond_wait(&s,&m)),("Couldn't wait"))}
- #define SIGNAL(s) \
- {IS_NZERO((err=pthread_cond_signal(&s)),("Couldn't send signal"))}
- #define BROADCAST(s) \
- {IS_NZERO((err=pthread_cond_broadcast(&s)),("Couldn't broadcast the signal"))}
- /* TYPE DEF */
- typedef enum color {
- NOCOLOR,
- RED,
- BLUE,
- GREEN,
- WHITE,
- BLACK
- } color;
- typedef struct node {
- color clr;
- struct node* next;
- } node;
- /* GLOBAL VAR */
- static node* head = NULL;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t cond_r = PTHREAD_COND_INITIALIZER, cond_w = PTHREAD_COND_INITIALIZER;
- static int working_r = 0, working_w = 0, waiting_r = 0, waiting_w = 0;
- /* FUNCTION DEF */
- void* writer(void* args);
- void* reader(void* args);
- char* getColorName(color clr);
- void gcollector();
- static void cleanup_handler(void* arg);
- /* FUNCTION IMP*/
- int main(){
- char ctrl;
- int err = 0, status = 0;
- pthread_t tid_wr0 = NULL, tid_wr1 = NULL;
- pthread_t tid_re0 = NULL, tid_re1 = NULL, tid_re2 = NULL, tid_re3 = NULL, tid_re4 = NULL;
- PRINT_INFO;
- /* Creating writers's threads */
- IS_NZERO((err = pthread_create(&tid_wr0, NULL, &writer, (void*)0)),"Couldn't create writer no. 0");
- IS_NZERO((err = pthread_create(&tid_wr1, NULL, &writer, (void*)1)),"Couldn't create writer no. 1");
- /* Creating readers's threads */
- IS_NZERO((err = pthread_create(&tid_re0, NULL, &reader, (void*) RED)),"Couldn't create the RED reader");
- IS_NZERO((err = pthread_create(&tid_re1, NULL, &reader, (void*) BLUE)),"Couldn't create the BLUE reader");
- IS_NZERO((err = pthread_create(&tid_re2, NULL, &reader, (void*) GREEN)),"Couldn't create the GREEN reader");
- IS_NZERO((err = pthread_create(&tid_re3, NULL, &reader, (void*) WHITE)),"Couldn't create the WHITE reader");
- IS_NZERO((err = pthread_create(&tid_re4, NULL, &reader, (void*) BLACK)),"Couldn't create the BLACK reader");
- /* Exit condition */
- while(ctrl != 'q'){
- scanf("%c",&ctrl);
- if(ctrl!='q') {PRINT_INFO;}
- else{
- /* Killing threads */
- IS_NZERO((err = pthread_cancel(tid_wr0)),"Couldn't kill writer no. 0");
- printf("[ Writer no. 0 killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_wr1)),"Couldn't kill writer no. 1");
- printf("[ Writer no. 1 killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_re0)),"Couldn't kill the RED reader");
- printf("[ RED reader killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_re1)),"Couldn't kill the BLUE reader");
- printf("[ BLUE reader killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_re2)),"Couldn't kill the GREEN reader");
- printf("[ GREEN reader killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_re3)),"Couldn't kill the WHITE reader");
- printf("[ WHITE reader killed ]\n");
- IS_NZERO((err = pthread_cancel(tid_re4)),"Couldn't kill the BLACK reader");
- printf("[ BLACK reader killed ]\n");
- /* Calling atexit */
- IS_NZERO((err=atexit(gcollector)),"Atexit failed! Possible memory leak");
- /* Waiting for dead threads */
- IS_NZERO((err=pthread_join(tid_wr0,(void*)&status)),"Join with writer no. 0 failed");
- IS_NZERO((err=pthread_join(tid_wr1,(void*)&status)),"Join with writer no. 1 failed");
- IS_NZERO((err=pthread_join(tid_re0,(void*)&status)),"Join with RED reader failed");
- IS_NZERO((err=pthread_join(tid_re1,(void*)&status)),"Join with BLUE reader failed");
- IS_NZERO((err=pthread_join(tid_re2,(void*)&status)),"Join with GREEN reader failed");
- IS_NZERO((err=pthread_join(tid_re3,(void*)&status)),"Join with WHITE reader failed");
- IS_NZERO((err=pthread_join(tid_re4,(void*)&status)),"Join with BLACK reader failed");
- }
- }
- return 0;
- }
- void* writer(void* args){
- unsigned int seed;
- int err = 0;
- color new_clr;
- node* new_node, *it;
- printf("[ Writer %d created]\n",(int)args);
- pthread_cleanup_push(cleanup_handler,(void*)NULL);
- while(1){
- /* Generating a new random color */
- if((int)args == 0) seed = time(0) * 2;
- else seed = time(0);
- new_clr = rand_r(&seed)%6;
- /* Locking the mutex */
- LOCK(mutex);
- /* Increasing waiting readers */
- waiting_w ++;
- /* Testing and resetting var */
- if((working_r)||(working_w)) WAIT(cond_w,mutex);
- waiting_w --;
- working_w ++;
- /* Unlocking the mutex */
- UNLOCK(mutex);
- /* Creating a new node with the generated color */
- IS_NULL((new_node = (node*) malloc(sizeof(node))),"Couldn't allocate new nodes");
- new_node->clr = new_clr;
- new_node->next = NULL;
- /* Attaching the new node to the list */
- if(head != NULL){
- it = head;
- while(it->next != NULL) it = it->next;
- it->next = new_node;
- } else head = new_node;
- printf("** Writer %d has done its job, attached %s to the list! **\n",(int) args, getColorName(new_clr));
- sleep(2);
- /* Locking the mutex */
- LOCK(mutex);
- /* Setting var */
- working_w --;
- /* Waking up all the readers or the other writer */
- if(waiting_r) BROADCAST(cond_r)
- else if(waiting_w) SIGNAL(cond_w)
- /* Unlocking the mutex */
- UNLOCK(mutex);
- }
- pthread_cleanup_pop(0);
- return (void*) 0;
- }
- void* reader(void* args){
- char* my_clr = getColorName((color) args);
- int err = 0, clr_counter = 0;
- node *it;
- printf("[ %s reader created ]\n",my_clr);
- pthread_cleanup_push(cleanup_handler,(void*)NULL);
- while(1){
- /* Resetting counter and it */
- clr_counter = 0;
- /* Locking mutex */
- LOCK(mutex);
- /* Testing and setting var*/
- waiting_r ++;
- if((working_w)||(waiting_w)) WAIT(cond_r,mutex);
- waiting_r --;
- working_r ++;
- /* Unlocking mutex */
- UNLOCK(mutex);
- /* Reading list */
- it = head;
- while(it != NULL){
- if(!strcmp(getColorName(it->clr),my_clr)) clr_counter ++;
- it = it->next;
- }
- printf("## I'm the %s reader, I've found %d hits on this run! ##\n",my_clr,clr_counter);
- sleep(1);
- /* Locking the mutex */
- LOCK(mutex);
- /* Testing and setting var*/
- working_r --;
- if((!working_r)&&(waiting_w)) SIGNAL(cond_w);
- /* Unlocking mutex */
- UNLOCK(mutex);
- }
- pthread_cleanup_pop(0);
- return (void*) 0;
- }
- char* getColorName(color clr){
- switch(clr){
- case RED : return "RED";
- case BLUE : return "BLUE";
- case GREEN : return "GREEN";
- case WHITE : return "WHITE";
- case BLACK : return "BLACK";
- default : return "NOCOLOR";
- }
- }
- void gcollector(){
- node* it = head;
- printf("[ Collecting some garbage... ]\n");
- while(it != NULL){
- it = it->next;
- free(head);
- head = it;
- }
- head = NULL;
- printf("[ Bye! ]\n");
- }
- static void cleanup_handler(void* arg){
- int err=0;
- printf("[ Running cleanup handler... ]\n");
- UNLOCK(mutex);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement