Thread-Specific Data
Thread-specific data, also known as thread-private data, is a mechanism for storing and finding data associated with a particular thread. The reason we call the data thread-specific, or thread-private, is that we’d like each thread to access its own separate copy of the data, without worrying about synchronizing access with other threads.
First, sometimes we need to maintain data on a per-thread basis.
The second reason for thread-private data is to provide a mechanism for adapting process-based interfaces to a multithreaded environment.
Before allocating thread-specific data, we need to create a key to associate with the data. The key will be used to gain access to the thread-specific data.
#include <pthread.h>
int pthread_key_create(pthread_key_t *keyp, void (*destroy)(void *));
We can break the association of a key with the thread-specific data values for all threads by calling pthread_key_delete.
#include <pthread.h>
int pthread_key_delete(pthread_key_t key);
#include <pthread.h>
pthread_once_t initflag=PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *initflag, void (*initfn)(void));
The initflag must be a nonlocal variable (i.e., global or static) and initialized to PTHREAD_ONCE_INIT.
Once a key is created, we can associate thread-specific data with the key by calling pthread_setspecific. We can obtain the address of the thread-specific data with pthread_getspecific.
#include <pthread.h>
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
#include <limits.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define MAXSTRINGSZ 4096
static pthread_key_t key;
static pthread_once_t init_done=PTHREAD_ONCE_INIT;
pthread_mutex_t env_mutex=PTHREAD_MUTEX_INIALIZER;
extern char **environ;
static void thread_init(void)
{
pthread_key_create(&key, free);
}
char *getenv(const char *name)
{
int i,len;
char *envbuf;
pthread_once(&init_done, thread_init);
pthread_mutex_lock(&env_mutex);
envbuf=(char*)pthread_getspecific(key);
if(envbuf==NULL)
{
envbuf=malloc(MAXSTRINGSZ);
if(envbuf==NULL)
{
pthread_mutex_unlock(&env_mutex);
return NULL;
}
pthread_setpecific(key,envbuf);
}
len=strlen(name);
for(i=0;environ[i]!=NULL;i++)
{
if((strncmp(name, environ[i],len)&&
(envrion[i][len]=='='))
{
strncpy(envbuf, &environ[i][len+1],MAXSTRINGSZ)
pthread_mutex_unlock(&env_mutex);
return envbuf;
}
}
pthread_mutex_unlock(&env_mutex);
return NULL;
}
A thread-safe, compatible version of getenv