13780abab762f1a5fd01a12679257354f8116820
1 /*****************************************************************************
2 * RRDtool 1.2.27 Copyright by Tobi Oetiker, 1997-2008
3 * This file: Copyright 2003 Peter Stamfest <peter@stamfest.at>
4 * & Tobias Oetiker
5 * Distributed under the GPL
6 *****************************************************************************
7 * rrd_thread_safe.c Contains routines used when thread safety is required
8 * for win32
9 *****************************************************************************
10 * $Id: rrd_thread_safe_nt.c 1286 2008-02-17 10:08:10Z oetiker $
11 *************************************************************************** */
13 #include <windows.h>
14 #include <string.h>
15 /* #include <error.h> */
16 #include "rrd.h"
17 #include "rrd_tool.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...
30 */
31 static void context_destroy_context(void)
32 {
33 DeleteCriticalSection(&CriticalSection);
34 TlsFree(context_key);
35 context_key_once=0;
36 }
37 static void context_init_context(void)
38 {
39 if (!InterlockedExchange(&context_key_once, 1)) {
40 context_key = TlsAlloc();
41 InitializeCriticalSection(&CriticalSection);
42 atexit(context_destroy_context);
43 }
44 }
45 struct rrd_context *rrd_get_context(void) {
46 struct rrd_context *ctx;
48 context_init_context();
50 ctx = TlsGetValue(context_key);
51 if (!ctx) {
52 ctx = rrd_new_context();
53 TlsSetValue(context_key, ctx);
54 }
55 return ctx;
56 }
57 #undef strerror
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;
70 }
71 /*
72 * there much be a re-entrant version of these somewhere in win32 land
73 */
74 struct tm* localtime_r(const time_t *timep, struct tm* result)
75 {
76 struct tm *local;
77 context_init_context();
79 EnterCriticalSection(&CriticalSection);
80 local = localtime(timep);
81 memcpy(result,local,sizeof(struct tm));
82 LeaveCriticalSection(&CriticalSection);
83 return result;
84 }
85 char* ctime_r(const time_t *timep, char* result)
86 {
87 char *local;
88 context_init_context();
90 EnterCriticalSection(&CriticalSection);
91 local = ctime(timep);
92 strcpy(result,local);
93 LeaveCriticalSection(&CriticalSection);
94 return result;
95 }
97 struct tm* gmtime_r(const time_t *timep, struct tm* result)
98 {
99 struct tm *local;
100 context_init_context();
102 EnterCriticalSection(&CriticalSection);
103 local = gmtime(timep);
104 memcpy(result,local,sizeof(struct tm));
105 LeaveCriticalSection(&CriticalSection);
106 return result;
107 }
109 /* implementation from Apache's APR library */
110 char *strtok_r(char *str, const char *sep, char **last)
111 {
112 char *token;
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))
121 ++str;
123 if (!*str) /* no more tokens */
124 return NULL;
126 token = str;
128 /* skip valid token characters to terminate token and
129 * prepare for the next call (will terminate at '\0)
130 */
131 *last = token + 1;
132 while (**last && !strchr(sep, **last))
133 ++*last;
135 if (**last) {
136 **last = '\0';
137 ++*last;
138 }
140 return token;
141 }