// Using multiple threads to copy files and using condition variables // Compile: gcc -o cond2 cond2.c -pthread #include #include #include #include #define MAX 5 #define BLOCK 1024 //Thread function protoype void * read_file( void *); /*** These are global ***/ /* create thread argument struct for thr_func() */ typedef struct _thread_data_t { int tid; char * file; } thread_data_t; //the condition variable will be protecting the global variable test_condition pthread_mutex_t lock_it = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_it = PTHREAD_COND_INITIALIZER; int test_condition = 0; int main(int argc, char *argv[]) { int i; int save_status = 0; pthread_t thread_id[MAX]; void *result; //Need a place to store the return value from each thread if ( argc < 2 || argc > MAX+1 ) { // check arg list printf("%s arg1, arg2, ... arg%d\n", *argv, MAX ); exit( 1 ); } printf("Copying the files named on the command line\n\n"); // create a thread_data_t argument array thread_data_t thr_data[argc - 1]; for (i = 0; i < argc - 1; ++i) { // generate threads thr_data[i].tid = i; thr_data[i].file = (char *)argv[i+1]; if( pthread_create(&thread_id[i], NULL, read_file, (void *) &thr_data[i]) != 0) { printf("pthread_create failure\n"); exit( 2 ); } } for (i = 0; i < argc - 1; ++i){ // wait for each thread if ( pthread_join(thread_id[i], &result) > 0 ) { printf("pthread_join failure\n"); exit( 3 ); } printf("Just released thread %d\n",i); if (*(int*)result > save_status) { save_status = *(int*)result; printf("Thread %d returns %d\n", i,*(int*)result); } free((int*)result); //Have to free memory allocated in the thread } if (save_status == 0 ) printf("\nAll files copied\n"); //No longer need the mutex and condition variable pthread_cond_destroy(&cond_it); pthread_mutex_destroy(&lock_it); exit (0); } // Open and copy to stdout the contents of the file void *read_file(void *fileinfo) { char buffer[BLOCK]; FILE *fp; int *ip = (int*)malloc(sizeof(int)); //This pointer will point at the return value int tid; *ip = 0; //Initialize the return value to zero thread_data_t *data = (thread_data_t *)fileinfo; tid = data->tid; pthread_mutex_lock(&lock_it); // lock stdout while (test_condition != tid ) pthread_cond_wait(&cond_it,&lock_it); // test_condition is true, release mutex pthread_mutex_unlock(&lock_it); if((fp = fopen((char *)data->file,"r")) == NULL ) { //Try to open the external file // open was unsuccessful, so return a value of 1 *ip = 1; pthread_exit((void *)ip); } printf("Thread %2d copying file %s\n",tid,(char *)data->file); while ((fgets(buffer,BLOCK,fp)) != NULL) printf("%s",buffer); fclose(fp); //The file has been read // acquire the mutex, change the test_condition pthread_mutex_lock(&lock_it); test_condition++; pthread_cond_signal(&cond_it); pthread_mutex_unlock(&lock_it); //*ip should still be 0 pthread_exit((void *)ip); }