00001 /* 00002 Thread example (cleanup handler) 00003 AUP2, Sec. 5.17.5 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include <pthread.h> 00023 00024 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 00025 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 00026 00027 struct node { 00028 int n_number; 00029 struct node *n_next; 00030 } *head = NULL; 00031 00032 /*[thread_func]*/ 00033 static void cleanup_handler(void *arg) 00034 { 00035 free(arg); 00036 (void)pthread_mutex_unlock(&mtx); 00037 } 00038 00039 static void *thread_func(void *arg) 00040 { 00041 struct node *p = NULL; 00042 00043 pthread_cleanup_push(cleanup_handler, p); 00044 while (true) { 00045 ec_rv( pthread_mutex_lock(&mtx) ) 00046 while (head == NULL) 00047 ec_rv( pthread_cond_wait(&cond, &mtx) ) 00048 p = head; 00049 head = head->n_next; 00050 printf("Got %d from front of queue\n", p->n_number); 00051 free(p); 00052 ec_rv( pthread_mutex_unlock(&mtx) ) 00053 } 00054 pthread_cleanup_pop(false); 00055 return (void *)true; 00056 00057 EC_CLEANUP_BGN 00058 (void)pthread_mutex_unlock(&mtx); 00059 EC_FLUSH("thread_func") 00060 return (void *)false; 00061 EC_CLEANUP_END 00062 } 00063 /*[]*/ 00064 00065 int main(void) 00066 { 00067 pthread_t tid; 00068 int i; 00069 struct node *p; 00070 00071 ec_rv( pthread_create(&tid, NULL, thread_func, NULL) ) 00072 /*[tx6-main]*/ 00073 for (i = 0; i < 10; i++) { 00074 ec_null( p = malloc(sizeof(struct node)) ) 00075 p->n_number = i; 00076 ec_rv( pthread_mutex_lock(&mtx) ) 00077 p->n_next = head; 00078 head = p; 00079 ec_rv( pthread_cond_signal(&cond) ) 00080 ec_rv( pthread_mutex_unlock(&mtx) ) 00081 sleep(1); 00082 } 00083 ec_rv( pthread_cancel(tid) ) 00084 ec_rv( pthread_join(tid, NULL) ) 00085 printf("All done -- exiting\n"); 00086 return EXIT_SUCCESS; 00087 /*[]*/ 00088 00089 EC_CLEANUP_BGN 00090 return EXIT_FAILURE; 00091 EC_CLEANUP_END 00092 }