Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Histogram text analyzer for program 5.
- *
- * Author: Andrew Porter
- * Date: 04/13/2018
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <pthread.h>
- #include "concurrentBuffer.h"
- #define MAX_WORD 50
- #define MIN_WORD 6
- #ifndef BUFFER_SIZE
- #define BUFFER_SIZE 10
- #endif
- long glob_histogram[MAX_WORD+1];
- static char* getWord (FILE* f);
- static void *work_one(void *info);
- static void *work_two(void *buffer);
- typedef struct {
- FILE *fp;
- void *buffer;
- } INFO;
- /**
- * Histogram text analyzer for program 5.
- */
- int main (int argc, char *argv[])
- {
- if (argc < 2)
- {
- fprintf(stderr, "usage: ./histogram [file_names]\n");
- exit(-1);
- }
- // create concurrent buffer
- void *cBuffer = createConcurrentBuffer(BUFFER_SIZE);
- if (cBuffer == NULL)
- {
- fprintf(stderr, "can't create the concurrent buffer\n");
- exit(-1);
- }
- pthread_t thread1array[argc+1];
- pthread_t thread2array[argc+1];
- for (int i = 1; i < argc; i++)
- {
- // open the file to be read
- FILE *fp = fopen(argv[i], "r");
- if (fp == NULL)
- {
- fprintf(stderr, "can't open %s\n", argv[1]);
- exit(-1);
- }
- // create struct to pass info to first thread
- INFO *ip = malloc(sizeof(INFO));
- if (ip == NULL)
- {
- fprintf(stderr, "can't malloc the INFO struct\n");
- exit(-1);
- }
- ip->fp = fp;
- ip->buffer = cBuffer;
- // create the first thread
- pthread_t *thread1 = thread1array+i;
- if (pthread_create(thread1, NULL, work_one, ip) != 0)
- {
- fprintf(stderr, "can't create thread 1\n");
- exit(-1);
- }
- // create the second thread
- pthread_t *thread2 = thread2array+i;
- if (pthread_create(thread2, NULL, work_two, cBuffer) != 0)
- {
- fprintf(stderr, "can't create thread 2\n");
- exit(-1);
- }
- }
- // wait for threads to finish and sum partial results into global sum
- for (int i = 1; i < argc; i++)
- {
- // wait for the first thread to finish
- if (pthread_join(thread1array[i], NULL))
- {
- fprintf(stderr, "join for thread 1 fails\n");
- exit(-1);
- }
- // wait for the second thread to finish
- void *ret;
- if (pthread_join(thread2array[i], &ret))
- {
- fprintf(stderr, "join for thread 2 fails\n");
- exit(-1);
- }
- for (int i = 0; i < MAX_WORD+1; i++)
- {
- glob_histogram[i] += ((long*)ret)[i];
- }
- free(ret); // free return value
- }
- // free the concurrent buffer
- deleteConcurrentBuffer(cBuffer);
- // print the global histogram
- for (int i = 6; i < MAX_WORD+1; i++)
- {
- printf("%d %ld\n", i, glob_histogram[i]);
- }
- return 0;
- }
- /**
- * getWord from input file.
- * code used from serialHistrogram.c.
- *
- * @param file
- * @return char*
- */
- static char *getWord(FILE *fp)
- {
- char buf[MAX_WORD+1];
- int c;
- int i = 0;
- //read until a letter or EOF is seen
- c = getc(fp);
- while (!isalpha(c))
- {
- if (c == EOF)
- {
- return NULL;
- }
- c = getc(fp);
- }
- // now read until a non-letter or EOF is seen
- while (isalpha(c))
- {
- // if word too long, stop storing letters
- if (i < MAX_WORD)
- {
- buf[i] = tolower(c);
- }
- i += 1;
- c = getc(fp);
- }
- // if word too short or too long, can discard it and try to read another
- if ((i < MIN_WORD) || (i > MAX_WORD))
- {
- // just recurse
- return getWord(fp);
- }
- // otherwise make a safe copy of word
- else {
- buf[i] = 0;
- char *p = malloc(strlen(buf)+1);
- strcpy(p, buf);
- return p;
- }
- }
- /**
- * work function for the first thread (the producer)
- *
- * @param info
- * @return void
- */
- static void *work_one(void *info)
- {
- INFO *ip = info;
- // read the lines in the file
- char *word;
- while ((word = getWord(ip->fp)) != NULL)
- {
- putConcurrentBuffer(ip->buffer, word);
- }
- // put a NULL to indicate EOF
- putConcurrentBuffer(ip->buffer, NULL);
- // close the file
- fclose(ip->fp);
- // free the memory for the "info"
- free(info);
- return NULL;
- }
- /**
- * work function for the second thread (the consumer)
- *
- * @param info
- * @return void
- */
- static void *work_two(void *buffer)
- {
- // get lines from the buffer
- // and sum the number of characters in the line
- char *word;
- long* temp = malloc(sizeof(glob_histogram));
- if ( temp == NULL )
- {
- printf("malloc failed");
- exit(-1);
- }
- for (int i = 0; i < MAX_WORD+1; i++)
- {
- temp[i] = 0;
- }
- while ((word = getConcurrentBuffer(buffer)) != NULL)
- {
- temp[strlen(word)]++;
- free(word);
- }
- return (void*) temp;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement