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);
}