User Data


Problem

You have a counter routine from some old software. Everytime it is called it returns the next number. Now with your threaded program you still want it to return the next number for the thread.
static int i = 0;
int counter()
{
	return (++i);
}


Thread Specific Data

int pthread_key_create(pthread_key_t * key, void (*destructor(void *)) );

int pthread_key_delete(pthread_key_t key);

int pthread_setspecific(pthread_key_t * key, const void *value)

void * pthread_getspecific(pthread_key_t * key)


Fixed Problem

static pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t counter_key;
static counter_init = 0;

int counter()
{
    int *i;
    P_M_L(&counter_mutex);
    if (counter_init == 0) {
	if (pthread_key_create(&counter_key, free)) {
	    counter_init = 1;
	    P_M_U(&counter_mutex);
	    exit(1);
	}
    } 
    P_M_U(&counter_mutex);

    if ((i = pthread_getspecific(&counter_key)) == NULL)
	i = malloc(sizeof(int));
	pthread_setspecific(counter_key, &i)
    }
    return(++(*i));
}


Pet Peave

int pthread_getspecific(pthread_key_t * key, void **)


Cleanup Handlers

void pthread_cleanup_push(void (*routine)(void *), void *arg);

void pthread_cleanup_pop(int execute);
Often inmpelemted as ...
struct _pthread_handler_rec {
};

#define pthread_cleanup_push(rtn, arg) {				\
	struct _pthread_handler_rec __cleanup_handler, **__head; 	\
	__cleanup_handler.rtn = rtn;					\
	__cleanup_handler.arg = arg;					\
	head = pthread_getspecific(_pthread_handler_key);		\
	__cleanup_handler.next = *__head;				\
	*head = &__cleanup_handler;

#define pthread_cleanup_pop(ex)						\
	*__head = cleanup_handler.next;					\
	if (ex) cleanup_handler.rtn(__cleanup_handler.arg);		\
}


Thread Exit

extern void (*dest[])(void *);

void __pthread_cleanup(void)
{
    int key, i;
    void * data;

    for (i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS; i++) {
        for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
            if (data = pthread_getspecific(key) {
                if (data) {
                    pthread_setspecific(key, NULL);
                    if (dest[key]) {
                        dest[key](data);
                    }
                }
            }
        }
    }
}


[TOP] [BACK] [FORWARD]


Prepared by Chris Provenzano (proven@mit.edu)