1 /*****************************************************************************
2 * RRDtool 1.2.19 Copyright by Tobi Oetiker, 1997-2007
3 * This file: Copyright 2003 Peter Stamfest <peter@stamfest.at>
5 * Distributed under the GPL
6 *****************************************************************************
7 * rrd_thread_safe.c Contains routines used when thread safety is required
9 *****************************************************************************
11 *************************************************************************** */
15 /* #include <error.h> */
19 /* Key for the thread-specific rrd_context */
20 static DWORD context_key;
21 static CRITICAL_SECTION CriticalSection;
24 /* Once-only initialisation of the key */
25 static DWORD context_key_once = 0;
28 /* Free the thread-specific rrd_context - we might actually use
29 rrd_free_context instead...
31 static void context_destroy_context(void)
33 DeleteCriticalSection(&CriticalSection);
37 static void context_init_context(void)
39 if (!InterlockedExchange(&context_key_once, 1)) {
40 context_key = TlsAlloc();
41 InitializeCriticalSection(&CriticalSection);
42 atexit(context_destroy_context);
45 struct rrd_context *rrd_get_context(void) {
46 struct rrd_context *ctx;
48 context_init_context();
50 ctx = TlsGetValue(context_key);
52 ctx = rrd_new_context();
53 TlsSetValue(context_key, ctx);
58 const char *rrd_strerror(int err) {
59 struct rrd_context *ctx;
60 context_init_context();
62 ctx = rrd_get_context();
64 EnterCriticalSection(&CriticalSection);
65 strncpy(ctx->lib_errstr, strerror(err), ctx->errlen);
66 ctx->lib_errstr[ctx->errlen] = '\0';
67 LeaveCriticalSection(&CriticalSection);
69 return ctx->lib_errstr;
72 * there much be a re-entrant version of these somewhere in win32 land
74 struct tm* localtime_r(const time_t *timep, struct tm* result)
77 context_init_context();
79 EnterCriticalSection(&CriticalSection);
80 local = localtime(timep);
81 memcpy(result,local,sizeof(struct tm));
82 LeaveCriticalSection(&CriticalSection);
85 char* ctime_r(const time_t *timep, char* result)
88 context_init_context();
90 EnterCriticalSection(&CriticalSection);
93 LeaveCriticalSection(&CriticalSection);
97 struct tm* gmtime_r(const time_t *timep, struct tm* result)
100 context_init_context();
102 EnterCriticalSection(&CriticalSection);
103 local = gmtime(timep);
104 memcpy(result,local,sizeof(struct tm));
105 LeaveCriticalSection(&CriticalSection);
109 /* implementation from Apache's APR library */
110 char *strtok_r(char *str, const char *sep, char **last)
113 context_init_context();
116 if (!str) /* subsequent call */
117 str = *last; /* start where we left off */
119 /* skip characters in sep (will terminate at '\0') */
120 while (*str && strchr(sep, *str))
123 if (!*str) /* no more tokens */
128 /* skip valid token characters to terminate token and
129 * prepare for the next call (will terminate at '\0)
132 while (**last && !strchr(sep, **last))