1 /*****************************************************************************
2 * RRDtool 1.1.x Copyright Tobias Oetiker, 1997 - 2002
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 LeaveCriticalSection(&CriticalSection);
68 return ctx->lib_errstr;
71 * there much be a re-entrant version of these somewhere in win32 land
73 struct tm* localtime_r(const time_t *timep, struct tm* result)
76 context_init_context();
78 EnterCriticalSection(&CriticalSection);
79 local = localtime(timep);
80 memcpy(result,local,sizeof(struct tm));
81 LeaveCriticalSection(&CriticalSection);
84 char* ctime_r(const time_t *timep, char* result)
87 context_init_context();
89 EnterCriticalSection(&CriticalSection);
92 LeaveCriticalSection(&CriticalSection);
96 struct tm* gmtime_r(const time_t *timep, struct tm* result)
99 context_init_context();
101 EnterCriticalSection(&CriticalSection);
102 local = gmtime(timep);
103 memcpy(result,local,sizeof(struct tm));
104 LeaveCriticalSection(&CriticalSection);
108 /* implementation from Apache's APR library */
109 char *strtok_r(char *str, const char *sep, char **last)
112 context_init_context();
115 if (!str) /* subsequent call */
116 str = *last; /* start where we left off */
118 /* skip characters in sep (will terminate at '\0') */
119 while (*str && strchr(sep, *str))
122 if (!*str) /* no more tokens */
127 /* skip valid token characters to terminate token and
128 * prepare for the next call (will terminate at '\0)
131 while (**last && !strchr(sep, **last))