Real World Example


Pthread TAD


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


[TOP] [BACK] [FORWARD]


Prepared by Chris Provenzano (proven@mit.edu)