pthread_key_create() — Create thread-specific data key

Standards

Standards / Extensions C or C++ Dependencies

POSIX.4a
Single UNIX Specification, Version 3

both

POSIX(ON)

Format

#define _OPEN_THREADS
#include <pthread.h>

int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
SUSV3:
#define _UNIX03_THREADS
#include <pthread.h>

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

General description

Creates a key identifier, associated with key, and returns the key identifier into the storage area of type pthread_key_t. At this point, each of the threads in the application has the use of that key, and can set its own unique value by use of pthread_setspecific(). A thread can get its own unique value using pthread_getspecific().

The destructor routine may be called when the thread ends. It is called when a non-NULL value has been set for the key for this thread, using pthread_setspecific(), and the thread:
  • Calls pthread_exit()
  • Does a return from the start routine
  • Is canceled because of a pthread_cancel() request.

When called, the destructor routine is passed the value bound to the key by the use of pthread_setspecific().

Special behavior for C++: Because C and C++ linkage conventions are incompatible, pthread_key_create() cannot receive a C++ function pointer as the start routine function pointer If you attempt to pass a C++ function pointer to pthread_key_create(), the compiler will flag it as an error. You can pass a C or C++ function to pthread_key_create() by declaring it as extern "C".

Returned value

If successful, pthread_key_create() returns 0 and stores the newly created key identifier in key.

If unsuccessful, pthread_key_create() returns -1 and sets errno to one of the following values:
Error Code
Description
EAGAIN
There were not enough system resources to create another thread-specific data key, or the limit is exceeded for the total number of keys per process.
ENOMEM
There is not enough memory to create key.

Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_key_create() returns an error number to indicate the error.

Example

CELEBP34
⁄* CELEBP34 *⁄
#ifndef _OPEN_THREADS
#define _OPEN_THREADS
#endif

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>

#define threads 3
#define BUFFSZ  48
pthread_key_t   key;

void            *threadfunc(void *parm)
{
 int        status;
 void      *value;
 int        threadnum;
 int       *tnum;
 void      *getvalue;
 char       Buffer[BUFFSZ];

 tnum = parm;
 threadnum = *tnum;

 printf("Thread %d executing\n", threadnum);

 if (!(value = malloc(sizeof(Buffer))))
     printf("Thread %d could not allocate storage, errno = %d\n",
                                                  threadnum, errno);
 status = pthread_setspecific(key, (void *) value);
 if ( status <  0) {
    printf("pthread_setspecific failed, thread %d, errno %d",
                                                  threadnum, errno);
    pthread_exit((void *)12);
 }
 printf("Thread %d setspecific value: %d\n", threadnum, value);

 getvalue = 0;
 status = pthread_getspecific(key, &getvalue);
 if ( status <  0) {
    printf("pthread_getspecific failed, thread %d, errno %d",
                                                  threadnum, errno);
    pthread_exit((void *)13);
 }

 if (getvalue != value) {
   printf("getvalue not valid, getvalue=%d", (int)getvalue);
   pthread_exit((void *)68);
 }

 pthread_exit((void *)0);
}

void  destr_fn(void *parm)
{

   printf("Destructor function invoked\n");
   free(parm);
}


main() {
 int          getvalue;
 int          status;
 int          i;
 int          threadparm[threads];
 pthread_t    threadid[threads];
 int          thread_stat[threads];

 if ((status = pthread_key_create(&key, destr_fn )) < 0) {
    printf("pthread_key_create failed, errno=%d", errno);
    exit(1);
 }

 ⁄* create 3 threads, pass each its number *⁄
 for (i=0; i<threads; i++) {
    threadparm[i] = i+1;
    status = pthread_create( &threadid[i],
                             NULL,
                             threadfunc,
                             (void *)&threadparm[i]);
    if ( status <  0) {
       printf("pthread_create failed, errno=%d", errno);
       exit(2);
    }
  }

 for ( i=0; i<threads; i++) {
    status = pthread_join( threadid[i], (void *)&thread_stat[i]);
    if ( status <  0) {
       printf("pthread_join failed, thread %d, errno=%d\n", i+1, errno);
    }

    if (thread_stat[i] != 0)   {
        printf("bad thread status, thread %d, status=%d\n", i+1,
                                                   thread_stat[i]);
      }
  }

 exit(0);
}

Related information