/* pre: takes in int argc and char** argv command line arguments * post: runs the transfer1 program */ int main(int argc, char** argv) { struct s_threadArgs fillerArgs; struct s_threadArgs drainerArgs; pthread_t fillerThread; pthread_t drainerThread; char* inFile; char* outFile; int fillerWait; int drainerWait; if (argc != 5) { printf("%s\n", usage); exit(0); } inFile = argv[1]; outFile = argv[2]; fillerWait = atoi(argv[3]); drainerWait = atoi(argv[4]); /* setup thread args */ fillerArgs.waitTime = fillerWait; fillerArgs.fileName = inFile; drainerArgs.waitTime = drainerWait; drainerArgs.fileName = outFile; cbuf_init(); if (sem_init(&gl_sem, 0, 1) == -1) printError("unable to initialize semaphore"); printf("buffer size: %d\n", cbuf_space_available()); /* create 2 pthreads for filler and drainer */ if (pthread_create(&fillerThread, NULL, &start_filler, (void *) &fillerArgs)) printError("could not create filler thread"); if (pthread_create(&drainerThread, NULL, &start_drainer, (void *) &drainerArgs)) printError("could not create drainer thread"); #ifdef DEBUG printDebug("[main]\twaiting for threads..."); #endif /* wait for threads */ if (pthread_join(fillerThread, NULL)) printError("could not join filler thread"); if (pthread_join(drainerThread, NULL)) printError("could not join drainer thread"); #ifdef DEBUG printDebug("[main]\tfreeing memory and quitting..."); #endif cbuf_terminate(); if (sem_destroy(&gl_sem) == -1) printError("unable to destroy semaphore"); return 0; }
/* * Reads input file and writes each line to the buffer until no lines are left */ void *fill_buffer(void *p) { FILE *in_fp; /* file pointer to input file */ char *temp_buff = NULL; /* temporary buffer to read lines into before writing them into the shared buffer */ size_t in_len = 0; /* length of the input buffer */ ssize_t read; /* ssize_t struct for getting return of getline */ int done = 0; /* int to signal the thread to stop */ int ret = 0; /* return code of the thread (0 by default) */ /* try to open input file for reading */ if ((in_fp = fopen(env.in_name, "r")) == NULL) { perror("fopen input"); ret = -1; pthread_exit(&ret); } while (1) { if (usleep(env.fill_sleep) < 0) { perror("usleep fill_thread"); ret = -1; break; } /* only read next line if temp_buff is set to NULL */ if (temp_buff == NULL) { /* read line from input file into temporary buffer */ read = getline(&temp_buff, &in_len, in_fp); /* error checking */ if (read == -1 && errno > 0) { perror("getline"); ret = -1; break; } else if (read == -1 && errno == 0) { /* finished with input file */ free(temp_buff); temp_buff = "QUIT"; read = 4; done = 1; } } /* wait for mutex lock */ if (pthread_mutex_lock(&env.lock) != 0) { perror("pthread_mutex_lock fill_thread"); ret = -1; break; } /* wait on space_avail condition variable if there is no available space in shared buffer*/ if (!cbuf_space_available()) { if (pthread_cond_wait(&env.space_avail, &env.lock) != 0) { perror("pthread_cond_wait fill_thread"); ret = -1; break; } } /* --------------------------CRITICAL SECTION-------------------------- */ /* check if there is enough free space in shared buffer */ if (cbuf_space_available() >= read + 1) { /* load the string in from the temp_buff */ cbuf_copy_in(temp_buff); } else { printf("fill thread: could not write [%s] -- not enough space (%d)\n", temp_buff, cbuf_space_available()); } /* --------------------------CRITICAL SECTION-------------------------- */ /* signal to thread waiting on data_avail condition variable */ if (pthread_cond_signal(&env.data_avail) != 0) { perror("pthread_cond_signal fill_thread"); ret = -1; break; } /* release mutex lock */ if (pthread_mutex_unlock(&env.lock) != 0) { perror("pthread_mutex_unlock fill_thread"); ret = -1; break; } printf("fill thread: wrote [%s] to buffer (nwritten=%d)\n", temp_buff, (int)(read + 1)); /* if not done ready temp_buff to read another line from the input file (or break if finished reading) */ if (!done) { free(temp_buff); temp_buff = NULL; } else { break; } } printf("fill thread: exiting\n"); fclose(in_fp); pthread_exit(&ret); }
static void * fill_func(void *argument) { _thread_arg *arg; int *ret; FILE *f; size_t line_len; char *line, *line_t; char *quit = "QUIT"; ssize_t readn, readn_t; useconds_t sleep_time; int space_remain, len_copy_in; int i; arg = (_thread_arg *)argument; f = arg->f; sleep_time = arg->time; if ((ret = (int *)malloc(sizeof(int))) == NULL) HANDLE_ERROR("fill_thread: malloc"); *ret = 0; line = NULL; while (1) { readn_t = readn = getline(&line, &line_len, f); line_t = line; if (readn == -1) { readn_t = strlen(quit); line_t = quit; } for (i = 0; i < readn_t + 1; ++i) if (sem_wait(&spaces) == -1) HANDLE_ERROR("sem_wait spaces"); while (1) { if (usleep(sleep_time) == -1) HANDLE_ERROR("usleep"); if (sem_wait(&sem) == -1) HANDLE_ERROR("sem_wait"); space_remain = cbuf_space_available(); if (space_remain < readn_t + 1) { /* this condition will never happen */ printf("fill thread: could not write [%s] -- not enough space (%d)\n", line_t, space_remain); if (sem_post(&sem) == -1) HANDLE_ERROR("sem_post"); } else { len_copy_in = cbuf_copy_in(line_t); printf("fill thread: wrote [%s] into buffer (nwritten=%d)\n", line_t, len_copy_in); if (sem_post(&sem) == -1) HANDLE_ERROR("sem_post"); break; } } if (sem_post(&items) == -1) HANDLE_ERROR("sem_post items"); if (readn == -1) break; } free(line); return (void *)ret; }