Real World Example
#include <pthread.h> #include <sys/cdefs.h> typedef struct pthread_tad_t { struct tad_start * dead; pthread_mutex_t mutex; pthread_cond_t cond; unsigned int count_current; unsigned int count_max; } pthread_tad_t; /* * New functions */ __BEGIN_DECLS int pthread_tad_create __P((pthread_tad_t *, pthread_t *, pthread_attr_t *, void *(*routine)(), void *)); int pthread_tad_join __((pthread_tad_t *, pthread_t *, void **); int pthread_tad_count __P((pthread_tad_t *)); int pthread_tad_wait __P((pthread_tad_t *, unsigned int)); int pthread_tad_init __P((pthread_tad_t *, unsigned int)); int pthread_tad_destroy __P((pthread_tad_t *));
#include "pthreadutil.h" #include <stdio.h> #include <errno.h> struct tad_start { struct tad_start *next; pthread_tad_t * tad; void * (*routine)(); void * arg; pthread_t id; }; static void pthread_tad_done(void * arg) { struct tad_start * tad_start = arg; pthread_tad_t * tad = tad_start->tad; pthread_mutex_lock(&tad->mutex); pthread_cond_broadcast(&tad->cond); tad_start->next = tad->dead; tad->dead = tad_start; --tad->count_current; pthread_mutex_unlock(&tad->mutex); } static void * pthread_tad_start(struct tad_start * tad_start) { void * ret; pthread_cleanup_push(pthread_tad_done, tad_start); ret = tad_start->routine(tad_start->arg); pthread_cleanup_pop(1); return(ret); } int pthread_tad_create(pthread_tad_t * tad, pthread_t *thread_id, pthread_attr_t *attr, void * (*routine)(), void * arg) { struct tad_start * tad_start; int ret; pthread_mutex_lock(&tad->mutex); while (tad->count_max && (tad->count_current >= tad->count_max)) pthread_cond_wait(&tad->cond, &tad->mutex); if ((tad_start = malloc(sizeof(struct tad_start))) == NULL) { pthread_mutex_unlock(&tad->mutex); return(ENOMEM); } tad_start->tad = tad; tad_start->arg = arg; tad_start->routine = routine; if ((ret = pthread_create(thread_id, attr, pthread_tad_start, tad_start))) { tad_start->id = thread_id; tad->count_current++; } else { free(tad_start); } pthread_mutex_unlock(&tad->mutex); return(ret); } int pthread_tad_join(pthread_tad_t * tad, pthread_t * thread, void ** status) { struct tad_start **ts; int ret; pthread_mutex_lock(&tad->mutex); if (*thread == NULL) { while(tad->dead == NULL) pthread_cond_wait(&tad->cond, &tad->mutex); ret = pthread_join(tad->join->id, **status); *thread = tad->join->id; } else { for (; pthread_cond_wait(&tad->cond, &tad->mutex);) { for (ts = &tad->dead; (*ts); ts = &((*ts)->next)) { if (pthread_equal(thread, (*ts)->id)) { ret = pthread_join(*thread, status); (*ts) = (*ts)->next; goto done; } } } } done:; pthread_mutex_unlock(&tad->mutex); return(ret); } int pthread_tad_count(pthread_tad_t * tad) { int ret; pthread_mutex_lock(&tad->mutex); ret = tad->count_current; pthread_mutex_unlock(&tad->mutex); return(ret); } int pthread_tad_wait(pthread_tad_t * tad, unsigned int count) { if ((tad->count_max) && (tad->count_max < count)) { return(EINVAL); } pthread_mutex_lock(&tad->mutex); while (tad->count_current > count) pthread_cond_wait(&tad->cond, &tad->mutex); pthread_mutex_unlock(&tad->mutex); return(OK); } int pthread_tad_init(pthread_tad_t * tad, unsigned int max_count) { int ret; if ((ret = pthread_mutex_init(&tad->mutex, NULL)) == OK) { if (ret = pthread_cond_init(&tad->cond, NULL)) { pthread_mutex_destroy(&tad->mutex); } else { tad->count_max = max_count; tad->count_current = 0; tad->dead = NULL; } } return(ret); } /* * User is responsible to make sure their are no threads running * or waiting to be joined with */ int pthread_tad_destroy(pthread_tad_t * tad) { int ret; if ((ret = pthread_mutex_destroy(&tad->mutex)) == OK) { ret = pthread_cond_destroy(&tad->cond); } else { pthread_cond_destroy(&tad->cond); } tad->count_max = NOTOK; return(ret); }