/* File: mythread.c Author: Xiuwen Liu Created on: Sept. 25, 2003 Description: It includes a set of functions used by threads. Compile: See makefile */ #define MYTHREADS_SOURCE_C_C #include "mythreads.h" void * Producer(void *arg) { FILE *fp; int ch, ch1; char aword[MAX_WORD_LEN]; int len; int matching_tag; int k; char *pattern = "From "; int nmeg; int prev; MESSAGE_INFO amessage; int priority; // We let the producer run first priority = (1+NUM_THREADS) * 5; if (priority > 127) priority = 127; thr_setprio(thr_self(), priority); nmeg = 0; for(k=0; k < (mailbox_len-strlen(pattern)); k++) { if (((mailbox[k] == '\n') && (mailbox[k+1] == '\n')) || (k==0)) { if ((strncmp(&(mailbox[k+2]), pattern, strlen(pattern)) ==0) || ((k==0) && strncmp(&(mailbox[k]), pattern, strlen(pattern)) ==0)) { if (nmeg > 0) { mailbox[k+1] = '\0'; amessage.beginning = prev; amessage.end = k; amessage.message_id = nmeg; Produce_A_Message(&amessage); } nmeg++; if (k > 0) { prev = k+2; } else { prev = k; } } } } k = mailbox_len-1; amessage.beginning = prev; amessage.end = k; amessage.message_id = nmeg; Produce_A_Message(&amessage); printf("Producer (thread %d) produced %d messages\n", thr_self(), nmeg); return (void *)NULL; } void *Consumer(void *arg) { CONSUMER_INFO *info; int *wordsCount; int k, pos, tmp; MESSAGE_INFO amessage; char *temp_buf; FILE *fp; int max, class; int priority; int processed; int flags; sleep(2); processed = 0; // We let the producer run first priority = (5+NUM_THREADS) * 5/2; if (priority > 127) priority = 127; thr_setprio(thr_self(), priority); thr_yield(); info = (CONSUMER_INFO *)arg; printf("Consumer (thread %d) started.\n", thr_self()); wordsCount = (int *)malloc(sizeof(int) * info->nwords); temp_buf = (char *)NULL; /* Add your program for consumer here */ while(Consume_A_Message(&amessage)>=0) { processed ++; for (k=0; k < info->nwords; k++) { wordsCount[k] = 0; } if (temp_buf != NULL) { free(temp_buf); } temp_buf = (char *)malloc(sizeof(char) * (amessage.end-amessage.beginning+1)); pos = amessage.beginning; // Here we skip the headers // Note that the headers will be ended by two consective '\n' 's while(pos < amessage.end) { if ((mailbox[pos] == '\n') && (mailbox[pos+1] == '\n') ) { pos += 2; break; } pos++; } flags =1; // We find the next one that is not a while space while(pos <= amessage.end) { while (pos <= amessage.end) { if (isspace(mailbox[pos])) pos++; else break; } if (pos > amessage.end) break; // We read the next word. This is not the optimal to do the matching if (sscanf(&(mailbox[pos]), "%s", temp_buf) ==1) { for (k=0; k < info->nwords; k++) { if (strcasecmp(info->words[k].word, temp_buf) ==0) { wordsCount[k]++; } } pos += strlen(temp_buf); } else { break; } //printf("Consumer: %s\n", aword); } printf("Filtered words' occurrence report in message %d (%d -> %d).\n", amessage.message_id,amessage.beginning,amessage.end); max = wordsCount[0]; class = info->words[0].category; for (k=0; k < info->nwords; k++) { printf("\t%s (%d):\t\t%d\n", info->words[k].word, info->words[k].category, wordsCount[k]); // We add this to the total tmp = info->words[k].saved_messages; thr_yield(); tmp += wordsCount[k]; thr_yield(); info->words[k].saved_messages = tmp; thr_yield(); if (max < wordsCount[k]) { max = wordsCount[k]; class = info->words[k].category; } } if (max <= 0) { class = 0; } for (k=0; k < info->ncategories; k++) { if (info->categories[k].category == class) break; } if (k >= info->ncategories) { fprintf(stderr, "%d cateogry was not found ", class); fprintf(stderr, "and default is used instead.\n"); class = 0; } else { class = k; } /* Now save the message to the corresponding folder */ printf("Thead %d Save message %d (%d -> %d) to folder %s (%d).\n", thr_self(), amessage.message_id,amessage.beginning,amessage.end, info->categories[class].word, info->categories[class].category); fp = fopen(info->categories[class].word,"ab"); if (fp == NULL) { fprintf(stderr,"Could not open file \"%s\" for appending.\n", info->categories[class].word); fprintf(stderr,"Please change the permission of the file.\n"); } else { for (k=amessage.beginning; k <= amessage.end; k++) { if (isascii((int)mailbox[k])) { fputc((int)mailbox[k], fp); thr_yield(); } } fputc((int)'\n', fp); fclose(fp); } k = info->categories[class].saved_messages; thr_yield(); k = k + 1; thr_yield(); info->categories[class].saved_messages = k; if ((random()%2) ==0) sleep(1); } free(wordsCount); if (temp_buf != NULL) { free(temp_buf); } printf("Consumer thread %d is done with %d messaged processed.\n", thr_self(), processed); return (void *)NULL; } int Produce_A_Message(MESSAGE_INFO *amessage) { int i; /* Add to the shared buffer here */ /* Remember that you need to add concurrency control at here */ shared_buf[nextp] = *amessage; nextp = (nextp+1) % message_buf_size; return i; } int Consume_A_Message(MESSAGE_INFO *amessage) { //sleep(1); /* Add to the shared buffer here */ /* Remember that you need to add concurrency control at here */ int tmp; int saved_priority; int new_priority; if (done) return -1; *amessage = shared_buf[nextc]; thr_getprio(thr_self(), &saved_priority); new_priority = thr_self() * 5; if (new_priority > 127) new_priority = 127; thr_setprio(thr_self(), new_priority); thr_yield(); tmp = nextc; tmp = (nextc+1)%message_buf_size; thr_yield(); if ((random()%10) ==0) { sleep(1); } nextc = tmp; if (amessage->end >= (mailbox_len-2)) { done = 1; } thr_setprio(thr_self(), saved_priority); return 0; }