Next: Threads and Signal Handling, Previous: POSIX Semaphores, Up: POSIX Threads
Programs often need global or static variables that have different values in different threads. Since threads share one memory space, this cannot be achieved with regular variables. Thread-specific data is the POSIX threads answer to this need.
Each thread possesses a private memory block, the thread-specific data
area, or TSD area for short. This area is indexed by TSD keys. The TSD
area associates values of type void * to TSD keys. TSD keys are
common to all threads, but the value associated with a given TSD key can
be different in each thread.
For concreteness, the TSD areas can be viewed as arrays of void *
pointers, TSD keys as integer indices into these arrays, and the value
of a TSD key as the value of the corresponding array element in the
calling thread.
When a thread is created, its TSD area initially associates NULL
with all keys.
pthread_key_createallocates a new TSD key. The key is stored in the location pointed to by key. There is a limit ofPTHREAD_KEYS_MAXon the number of keys allocated at a given time. The value initially associated with the returned key isNULLin all currently executing threads.The destr_function argument, if not
NULL, specifies a destructor function associated with the key. When a thread terminates viapthread_exitor by cancellation, destr_function is called on the value associated with the key in that thread. The destr_function is not called if a key is deleted withpthread_key_deleteor a value is changed withpthread_setspecific. The order in which destructor functions are called at thread termination time is unspecified.Before the destructor function is called, the
NULLvalue is associated with the key in the current thread. A destructor function might, however, re-associate non-NULLvalues to that key or some other key. To deal with this, if after all the destructors have been called for all non-NULLvalues, there are still some non-NULLvalues with associated destructors, then the process is repeated. The LinuxThreads implementation stops the process afterPTHREAD_DESTRUCTOR_ITERATIONSiterations, even if some non-NULLvalues with associated descriptors remain. Other implementations may loop indefinitely.
pthread_key_createreturns 0 unlessPTHREAD_KEYS_MAXkeys have already been allocated, in which case it fails and returnsEAGAIN.
pthread_key_deletedeallocates a TSD key. It does not check whether non-NULLvalues are associated with that key in the currently executing threads, nor call the destructor function associated with the key.If there is no such key key, it returns
EINVAL. Otherwise it returns 0.
pthread_setspecificchanges the value associated with key in the calling thread, storing the given pointer instead.If there is no such key key, it returns
EINVAL. Otherwise it returns 0.
pthread_getspecificreturns the value currently associated with key in the calling thread.If there is no such key key, it returns
NULL.
The following code fragment allocates a thread-specific array of 100 characters, with automatic reclaimation at thread exit:
/* Key for the thread-specific buffer */
static pthread_key_t buffer_key;
/* Once-only initialisation of the key */
static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
/* Allocate the thread-specific buffer */
void buffer_alloc(void)
{
pthread_once(&buffer_key_once, buffer_key_alloc);
pthread_setspecific(buffer_key, malloc(100));
}
/* Return the thread-specific buffer */
char * get_buffer(void)
{
return (char *) pthread_getspecific(buffer_key);
}
/* Allocate the key */
static void buffer_key_alloc()
{
pthread_key_create(&buffer_key, buffer_destroy);
}
/* Free the thread-specific buffer */
static void buffer_destroy(void * buf)
{
free(buf);
}