static void * drain_func(void *argument) { _thread_arg *arg; int *ret; FILE *f; char *line; useconds_t sleep_time; int len_copy_out; int i; arg = (_thread_arg *)argument; f = arg->f; sleep_time = arg->time; if ((ret = (int *)malloc(sizeof(int))) == NULL) HANDLE_ERROR("drain_thread: malloc"); *ret = 0; if ((line = (char *)malloc(sizeof(char) * CBUF_CAPACITY)) == NULL) HANDLE_ERROR("drain_thread: malloc line"); while (1) { if (usleep(sleep_time) == -1) HANDLE_ERROR("usleep"); if (sem_wait(&items) == -1) HANDLE_ERROR("sem_wait items"); if (sem_wait(&sem) == -1) HANDLE_ERROR("sem_wait"); if (!cbuf_data_is_available()) { printf("drain thread: no new string in buffer\n"); if (sem_post(&sem) == -1) HANDLE_ERROR("sem_post"); } else { len_copy_out = cbuf_copy_out(line); printf("drain thread: read [%s] from buffer (nread=%d)\n", line, len_copy_out); if (sem_post(&sem) == -1) HANDLE_ERROR("sem_post"); if (strcmp(line, "QUIT") == 0) break; fwrite(line, len_copy_out - 1, 1, f); } for (i = 0; i < len_copy_out; ++i) if (sem_post(&spaces) == -1) HANDLE_ERROR("sem_post sapces"); } free(line); return (void *)ret; }
/* * Drains the buffer and writes each line to output file until "QUIT" is read */ void *drain_buffer(void *p) { FILE *out_fp; /* file pointer to output file */ size_t len = 32 * sizeof(char); /* length of temp_buff */ size_t read_ret; /* number of bytes copied out of the shared buffer */ char *temp_buff = (char*)malloc(len); /* temp buffer for reading from shared buffer */ int done = 0; /* int to signal the thread to stop */ int ret = 0; /* return code of the thread * (0 by default) */ /* try to open output file for writing */ if ((out_fp = fopen(env.out_name, "w")) == NULL) { perror("fopen output"); ret = -1; pthread_exit(&ret); } while (1) { if (usleep(env.drain_sleep) < 0) { perror("usleep drain_thread"); ret = -1; break; } /* wait for mutex lock */ if (pthread_mutex_lock(&env.lock) != 0) { perror("pthread_mutex_lock drain_thread"); ret = -1; break; } /* wait on data_avail condition variable if there is no data available */ if (!cbuf_data_is_available()) { if (pthread_cond_wait(&env.data_avail, &env.lock) != 0) { perror("pthread_cond_wait drain_thread"); ret = -1; break; } } /* --------------------------CRITICAL SECTION-------------------------- */ /* read string out of shared buffer */ read_ret = cbuf_copy_out(temp_buff); printf("drain thread: read [%s] from buffer (nread=%d)\n", temp_buff, (int)read_ret); /* if drain thread reads "QUIT" break and exit */ if (strcmp(temp_buff, "QUIT") == 0) { done = 1; } else { /* write from temp buffer to output file */ if (fwrite(temp_buff, strlen(temp_buff), 1, out_fp) <= 0) { perror("fwrite"); ret = -1; break; } } /* --------------------------CRITICAL SECTION-------------------------- */ /* signal to thread waiting on space_avail condition variable */ if (pthread_cond_signal(&env.space_avail) != 0) { perror("pthread_cond_signal drain_thread"); ret = -1; break; } /* release mutex lock */ if (pthread_mutex_unlock(&env.lock) != 0) { perror("pthread_mutex_unlock drain_thread"); ret = -1; break; } if (done) { break; } } printf("drain thread: exiting\n"); fclose(out_fp); pthread_exit(&ret); }