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_create
allocates a new TSD key. The key is stored in
the location pointed to by key. There is a limit of
PTHREAD_KEYS_MAX
on the number of keys allocated at a given
time. The value initially associated with the returned key is
NULL
in all currently executing threads.
The destr_function argument, if not NULL
, specifies a
destructor function associated with the key. When a thread terminates
via pthread_exit
or 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 with
pthread_key_delete
or a value is changed with
pthread_setspecific
. The order in which destructor functions are
called at thread termination time is unspecified.
Before the destructor function is called, the NULL
value is
associated with the key in the current thread. A destructor function
might, however, re-associate non-NULL
values to that key or some
other key. To deal with this, if after all the destructors have been
called for all non-NULL
values, there are still some
non-NULL
values with associated destructors, then the process is
repeated. The LinuxThreads implementation stops the process after
PTHREAD_DESTRUCTOR_ITERATIONS
iterations, even if some
non-NULL
values with associated descriptors remain. Other
implementations may loop indefinitely.
pthread_key_create
returns 0 unless PTHREAD_KEYS_MAX
keys
have already been allocated, in which case it fails and returns
EAGAIN
.
pthread_key_delete
deallocates a TSD key. It does not check
whether non-NULL
values 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_setspecific
changes 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_getspecific
returns 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); }
Go to the first, previous, next, last section, table of contents.