* replaced __thread with pthread_key_t/pthread_setspecific

* use pthread_once to initialize the request handler
This commit is contained in:
Tobias Brunner
2008-02-05 09:31:21 +00:00
parent e6b50b3fce
commit cdd33ec665
+34 -15
View File
@@ -27,6 +27,7 @@
#include <library.h> #include <library.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <pthread.h>
#include <ClearSilver/ClearSilver.h> #include <ClearSilver/ClearSilver.h>
typedef struct private_request_t private_request_t; typedef struct private_request_t private_request_t;
@@ -58,22 +59,28 @@ struct private_request_t {
}; };
/** /**
* thread specific FCGX_Request, used for ClearSilver cgiwrap callbacks. * key to a thread specific FCGX_Request, used for ClearSilver cgiwrap callbacks.
* ClearSilver cgiwrap is not threadsave, so we use a private * ClearSilver cgiwrap is not threadsave, so we use a private
* context for each thread. * context for each thread.
*/ */
static __thread FCGX_Request *req; static pthread_key_t req_key;
/** /**
* length of param list in req->envp * length of param list in req->envp
*/ */
static __thread int req_env_len; static pthread_key_t req_env_len_key;
/**
* control variable for pthread_once
*/
pthread_once_t once = PTHREAD_ONCE_INIT;
/** /**
* fcgiwrap read callback * fcgiwrap read callback
*/ */
static int read_cb(void *null, char *buf, int size) static int read_cb(void *null, char *buf, int size)
{ {
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
return FCGX_GetStr(buf, size, req->in); return FCGX_GetStr(buf, size, req->in);
} }
@@ -82,6 +89,7 @@ static int read_cb(void *null, char *buf, int size)
*/ */
static int writef_cb(void *null, const char *format, va_list args) static int writef_cb(void *null, const char *format, va_list args)
{ {
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
FCGX_VFPrintF(req->out, format, args); FCGX_VFPrintF(req->out, format, args);
return 0; return 0;
} }
@@ -90,6 +98,7 @@ static int writef_cb(void *null, const char *format, va_list args)
*/ */
static int write_cb(void *null, const char *buf, int size) static int write_cb(void *null, const char *buf, int size)
{ {
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
return FCGX_PutStr(buf, size, req->out); return FCGX_PutStr(buf, size, req->out);
} }
@@ -99,7 +108,7 @@ static int write_cb(void *null, const char *buf, int size)
static char *getenv_cb(void *null, const char *key) static char *getenv_cb(void *null, const char *key)
{ {
char *value; char *value;
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
value = FCGX_GetParam(key, req->envp); value = FCGX_GetParam(key, req->envp);
return value ? strdup(value) : NULL; return value ? strdup(value) : NULL;
} }
@@ -120,7 +129,8 @@ static int iterenv_cb(void *null, int num, char **key, char **value)
{ {
*key = NULL; *key = NULL;
*value = NULL; *value = NULL;
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
int req_env_len = (int)pthread_getspecific(req_env_len_key);
if (num < req_env_len) if (num < req_env_len)
{ {
char *eq; char *eq;
@@ -256,13 +266,24 @@ static void destroy(private_request_t *this)
free(this); free(this);
} }
/**
* This initialization method is guaranteed to run only once
* for all threads.
*/
static void init(void)
{
cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
getenv_cb, putenv_cb, iterenv_cb);
pthread_key_create(&req_key, NULL);
pthread_key_create(&req_env_len_key, NULL);
}
/* /*
* see header file * see header file
*/ */
request_t *request_create(FCGX_Request *request, bool debug) request_t *request_create(FCGX_Request *request, bool debug)
{ {
NEOERR* err; NEOERR* err;
static bool initialized = FALSE;
private_request_t *this = malloc_thing(private_request_t); private_request_t *this = malloc_thing(private_request_t);
this->public.get_path = (char*(*)(request_t*))get_path; this->public.get_path = (char*(*)(request_t*))get_path;
@@ -277,21 +298,19 @@ request_t *request_create(FCGX_Request *request, bool debug)
this->public.setf = (void(*)(request_t*, char *format, ...))setf; this->public.setf = (void(*)(request_t*, char *format, ...))setf;
this->public.destroy = (void(*)(request_t*))destroy; this->public.destroy = (void(*)(request_t*))destroy;
if (!initialized) pthread_once(&once, init);
{
cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
getenv_cb, putenv_cb, iterenv_cb);
initialized = TRUE;
}
this->req = request; this->req = request;
req = request; pthread_setspecific(req_key, (void*)request);
req_env_len = 0;
while (req->envp[req_env_len] != NULL) int req_env_len = 0;
while (request->envp[req_env_len] != NULL)
{ {
req_env_len++; req_env_len++;
} }
pthread_setspecific(req_env_len_key, (void*)req_env_len);
err = hdf_init(&this->hdf); err = hdf_init(&this->hdf);
if (!err) if (!err)
{ {