mirror of https://github.com/mkerrisk/man-pages
234 lines
8.1 KiB
Plaintext
234 lines
8.1 KiB
Plaintext
.\" Copyright (c) 2001-2003 The Open Group, All Rights Reserved
|
|
.TH "PTHREAD_KEY_CREATE" P 2003 "IEEE/The Open Group" "POSIX Programmer's Manual"
|
|
.\" pthread_key_create
|
|
.SH NAME
|
|
pthread_key_create \- thread-specific data key creation
|
|
.SH SYNOPSIS
|
|
.LP
|
|
\fB#include <pthread.h>
|
|
.br
|
|
.sp
|
|
int pthread_key_create(pthread_key_t *\fP\fIkey\fP\fB, void (*\fP\fIdestructor\fP\fB)(void*));
|
|
\fP
|
|
\fB
|
|
.br
|
|
\fP
|
|
.SH DESCRIPTION
|
|
.LP
|
|
The \fIpthread_key_create\fP() function shall create a thread-specific
|
|
data key visible to all threads in the process. Key
|
|
values provided by \fIpthread_key_create\fP() are opaque objects used
|
|
to locate thread-specific data. Although the same key value
|
|
may be used by different threads, the values bound to the key by \fIpthread_setspecific\fP()
|
|
are maintained on a per-thread basis and persist for the
|
|
life of the calling thread.
|
|
.LP
|
|
Upon key creation, the value NULL shall be associated with the new
|
|
key in all active threads. Upon thread creation, the value
|
|
NULL shall be associated with all defined keys in the new thread.
|
|
.LP
|
|
An optional destructor function may be associated with each key value.
|
|
At thread exit, if a key value has a non-NULL destructor
|
|
pointer, and the thread has a non-NULL value associated with that
|
|
key, the value of the key is set to NULL, and then the function
|
|
pointed to is called with the previously associated value as its sole
|
|
argument. The order of destructor calls is unspecified if
|
|
more than one destructor exists for a thread when it exits.
|
|
.LP
|
|
If, after all the destructors have been called for all non-NULL values
|
|
with associated destructors, there are still some
|
|
non-NULL values with associated destructors, then the process is repeated.
|
|
If, after at least {PTHREAD_DESTRUCTOR_ITERATIONS}
|
|
iterations of destructor calls for outstanding non-NULL values, there
|
|
are still some non-NULL values with associated destructors,
|
|
implementations may stop calling destructors, or they may continue
|
|
calling destructors until no non-NULL values with associated
|
|
destructors exist, even though this might result in an infinite loop.
|
|
.SH RETURN VALUE
|
|
.LP
|
|
If successful, the \fIpthread_key_create\fP() function shall store
|
|
the newly created key value at *\fIkey\fP and shall return
|
|
zero. Otherwise, an error number shall be returned to indicate the
|
|
error.
|
|
.SH ERRORS
|
|
.LP
|
|
The \fIpthread_key_create\fP() function shall fail if:
|
|
.TP 7
|
|
.B EAGAIN
|
|
The system lacked the necessary resources to create another thread-specific
|
|
data key, or the system-imposed limit on the total
|
|
number of keys per process {PTHREAD_KEYS_MAX} has been exceeded.
|
|
.TP 7
|
|
.B ENOMEM
|
|
Insufficient memory exists to create the key.
|
|
.sp
|
|
.LP
|
|
The \fIpthread_key_create\fP() function shall not return an error
|
|
code of [EINTR].
|
|
.LP
|
|
\fIThe following sections are informative.\fP
|
|
.SH EXAMPLES
|
|
.LP
|
|
The following example demonstrates a function that initializes a thread-specific
|
|
data key when it is first called, and
|
|
associates a thread-specific object with each calling thread, initializing
|
|
this object when necessary.
|
|
.sp
|
|
.RS
|
|
.nf
|
|
|
|
\fBstatic pthread_key_t key;
|
|
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
|
|
.sp
|
|
|
|
static void
|
|
make_key()
|
|
{
|
|
(void) pthread_key_create(&key, NULL);
|
|
}
|
|
.sp
|
|
|
|
func()
|
|
{
|
|
void *ptr;
|
|
.sp
|
|
|
|
(void) pthread_once(&key_once, make_key);
|
|
if ((ptr = pthread_getspecific(key)) == NULL) {
|
|
ptr = malloc(OBJECT_SIZE);
|
|
...
|
|
(void) pthread_setspecific(key, ptr);
|
|
}
|
|
...
|
|
}
|
|
\fP
|
|
.fi
|
|
.RE
|
|
.LP
|
|
Note that the key has to be initialized before \fIpthread_getspecific\fP()
|
|
or \fIpthread_setspecific\fP() can be used. The \fIpthread_key_create\fP()
|
|
call could either be explicitly made in a module initialization routine,
|
|
or it can be done implicitly by the first call to a module
|
|
as in this example. Any attempt to use the key before it is initialized
|
|
is a programming error, making the code below
|
|
incorrect.
|
|
.sp
|
|
.RS
|
|
.nf
|
|
|
|
\fBstatic pthread_key_t key;
|
|
.sp
|
|
|
|
func()
|
|
{
|
|
void *ptr;
|
|
.sp
|
|
|
|
/* KEY NOT INITIALIZED!!! THIS WON'T WORK!!! */
|
|
if ((ptr = pthread_getspecific(key)) == NULL &&
|
|
pthread_setspecific(key, NULL) != 0) {
|
|
pthread_key_create(&key, NULL);
|
|
...
|
|
}
|
|
}
|
|
\fP
|
|
.fi
|
|
.RE
|
|
.SH APPLICATION USAGE
|
|
.LP
|
|
None.
|
|
.br
|
|
.SH RATIONALE
|
|
.LP
|
|
.SS Destructor Functions
|
|
.LP
|
|
Normally, the value bound to a key on behalf of a particular thread
|
|
is a pointer to storage allocated dynamically on behalf of
|
|
the calling thread. The destructor functions specified with \fIpthread_key_create\fP()
|
|
are intended to be used to free this
|
|
storage when the thread exits. Thread cancellation cleanup handlers
|
|
cannot be used for this purpose because thread-specific data
|
|
may persist outside the lexical scope in which the cancellation cleanup
|
|
handlers operate.
|
|
.LP
|
|
If the value associated with a key needs to be updated during the
|
|
lifetime of the thread, it may be necessary to release the
|
|
storage associated with the old value before the new value is bound.
|
|
Although the \fIpthread_setspecific\fP() function could do this automatically,
|
|
this feature is not
|
|
needed often enough to justify the added complexity. Instead, the
|
|
programmer is responsible for freeing the stale storage:
|
|
.sp
|
|
.RS
|
|
.nf
|
|
|
|
\fBpthread_getspecific(key, &old);
|
|
new = allocate();
|
|
destructor(old);
|
|
pthread_setspecific(key, new);
|
|
\fP
|
|
.fi
|
|
.RE
|
|
.TP 7
|
|
\fBNote:\fP
|
|
The above example could leak storage if run with asynchronous cancellation
|
|
enabled. No such problems occur in the default
|
|
cancellation state if no cancellation points occur between the get
|
|
and set.
|
|
.sp
|
|
.LP
|
|
There is no notion of a destructor-safe function. If an application
|
|
does not call \fIpthread_exit\fP() from a signal handler, or if it
|
|
blocks any signal whose handler may call
|
|
\fIpthread_exit\fP() while calling async-unsafe functions, all functions
|
|
may be
|
|
safely called from destructors.
|
|
.SS Non-Idempotent Data Key Creation
|
|
.LP
|
|
There were requests to make \fIpthread_key_create\fP() idempotent
|
|
with respect to a given \fIkey\fP address parameter. This
|
|
would allow applications to call \fIpthread_key_create\fP() multiple
|
|
times for a given \fIkey\fP address and be guaranteed that
|
|
only one key would be created. Doing so would require the key value
|
|
to be previously initialized (possibly at compile time) to a
|
|
known null value and would require that implicit mutual-exclusion
|
|
be performed based on the address and contents of the \fIkey\fP
|
|
parameter in order to guarantee that exactly one key would be created.
|
|
.LP
|
|
Unfortunately, the implicit mutual-exclusion would not be limited
|
|
to only \fIpthread_key_create\fP(). On many implementations,
|
|
implicit mutual-exclusion would also have to be performed by \fIpthread_getspecific\fP()
|
|
and \fIpthread_setspecific\fP() in order to guard against using incompletely
|
|
stored or
|
|
not-yet-visible key values. This could significantly increase the
|
|
cost of important operations, particularly \fIpthread_getspecific\fP().
|
|
.LP
|
|
Thus, this proposal was rejected. The \fIpthread_key_create\fP() function
|
|
performs no implicit synchronization. It is the
|
|
responsibility of the programmer to ensure that it is called exactly
|
|
once per key before use of the key. Several straightforward
|
|
mechanisms can already be used to accomplish this, including calling
|
|
explicit module initialization functions, using mutexes, and
|
|
using \fIpthread_once\fP(). This places no significant burden on the
|
|
programmer,
|
|
introduces no possibly confusing \fIad hoc\fP implicit synchronization
|
|
mechanism, and potentially allows commonly used
|
|
thread-specific data operations to be more efficient.
|
|
.SH FUTURE DIRECTIONS
|
|
.LP
|
|
None.
|
|
.SH SEE ALSO
|
|
.LP
|
|
\fIpthread_getspecific\fP() , \fIpthread_key_delete\fP() , the Base
|
|
Definitions volume of IEEE\ Std\ 1003.1-2001, \fI<pthread.h>\fP
|
|
.SH COPYRIGHT
|
|
Portions of this text are reprinted and reproduced in electronic form
|
|
from IEEE Std 1003.1, 2003 Edition, Standard for Information Technology
|
|
-- Portable Operating System Interface (POSIX), The Open Group Base
|
|
Specifications Issue 6, Copyright (C) 2001-2003 by the Institute of
|
|
Electrical and Electronics Engineers, Inc and The Open Group. In the
|
|
event of any discrepancy between this version and the original IEEE and
|
|
The Open Group Standard, the original IEEE and The Open Group Standard
|
|
is the referee document. The original Standard can be obtained online at
|
|
http://www.opengroup.org/unix/online.html .
|