Cancellation
struct data { int arg; int ret; int sleeptime; pthread_t doer; pthread_t sleeper; pthread_mutex_t mutex; }; void * doer(struct data * data) { data->ret = foo(data->arg); pthread_mutex_lock(data->mutex); pthread_cleanup_push(pthread_mutex_unlock, data->mutex); pthread_testcancel(); pthread_cancel(data->sleeper); pthread_cleanup_pop(1); return(NULL); } void * sleeper(struct data * data) { sleep(data->sleeptime); pthread_mutex_lock(data->mutex); pthread_cleanup_push(pthread_mutex_unlock, data->mutex); pthread_testcancel(); pthread_cancel(data->doer); pthread_cleanup_pop(1); return(NULL); } int foo_timedwait(int arg, int sleeptime) { struct foo_data data; void * status; data.arg = arg; data.sleeptime = sleeptime; pthread_mutex_lock(&data.mutex); pthread_create(&data.sleeper, NULL, sleeper, &data); pthread_create(&data.doer, NULL, doer, &data); pthread_mutex_unlock(&data.mutex); { pthread_cleanup_push(pthread_cancel, data.doer); pthread_cleanup_push(pthread_detach, data.doer); { pthread_cleanup_push(pthread_cancel, data.sleeper); pthread_cleanup_push(pthread_detach, data.sleeper); pthread_join(data.sleeper, &status); pthred_cleanup_pop(0); pthred_cleanup_pop(0); } pthread_join(data.doer, &status); pthread_cleanup_pop(0); pthread_cleanup_pop(0); } if (status == PTHREAD_CANCELLED) { ret = ETIMEDOUT; else ret = data.ret; return(ret); }