e0dad45a565f8acacf40c6c17afd8b6ca28be816
1 /*****************************************************************************
2 * RRDtool 1.3.2 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$
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(
32 void)
33 {
34 DeleteCriticalSection(&CriticalSection);
35 TlsFree(context_key);
36 context_key_once = 0;
37 }
38 static void context_init_context(
39 void)
40 {
41 if (!InterlockedExchange((LONG*)(&context_key_once), 1)) {
42 context_key = TlsAlloc();
43 InitializeCriticalSection(&CriticalSection);
44 atexit(context_destroy_context);
45 }
46 }
47 rrd_context_t *rrd_get_context(
48 void)
49 {
50 rrd_context_t *ctx;
52 context_init_context();
54 ctx = (rrd_context_t*)TlsGetValue(context_key);
55 if (!ctx) {
56 ctx = rrd_new_context();
57 TlsSetValue(context_key, ctx);
58 }
59 return ctx;
60 }
63 /* this was added by the win32 porters Christof.Wegmann@exitgames.com */
65 rrd_context_t *rrd_force_new_context(
66 void)
67 {
68 rrd_context_t *ctx;
70 context_init_context();
72 ctx = rrd_new_context();
73 TlsSetValue(context_key, ctx);
75 return ctx;
76 }
79 #undef strerror
80 const char *rrd_strerror(
81 int err)
82 {
83 rrd_context_t *ctx;
85 context_init_context();
87 ctx = rrd_get_context();
89 EnterCriticalSection(&CriticalSection);
90 strncpy(ctx->lib_errstr, strerror(err), sizeof(ctx->lib_errstr));
91 ctx->lib_errstr[sizeof(ctx->lib_errstr) - 1] = '\0';
92 LeaveCriticalSection(&CriticalSection);
94 return ctx->lib_errstr;
95 }
97 /*
98 * there much be a re-entrant version of these somewhere in win32 land
99 */
100 struct tm *localtime_r(
101 const time_t *timep,
102 struct tm *result)
103 {
104 struct tm *local;
106 context_init_context();
108 EnterCriticalSection(&CriticalSection);
109 local = localtime(timep);
110 memcpy(result, local, sizeof(struct tm));
111 LeaveCriticalSection(&CriticalSection);
112 return result;
113 }
115 char *ctime_r(
116 const time_t *timep,
117 char *result)
118 {
119 char *local;
121 context_init_context();
123 EnterCriticalSection(&CriticalSection);
124 local = ctime(timep);
125 strcpy(result, local);
126 LeaveCriticalSection(&CriticalSection);
127 return result;
128 }
130 struct tm *gmtime_r(
131 const time_t *timep,
132 struct tm *result)
133 {
134 struct tm *local;
136 context_init_context();
138 EnterCriticalSection(&CriticalSection);
139 local = gmtime(timep);
140 memcpy(result, local, sizeof(struct tm));
141 LeaveCriticalSection(&CriticalSection);
142 return result;
143 }
145 /* implementation from Apache's APR library */
146 char *strtok_r(
147 char *str,
148 const char *sep,
149 char **last)
150 {
151 char *token;
153 context_init_context();
156 if (!str) /* subsequent call */
157 str = *last; /* start where we left off */
159 /* skip characters in sep (will terminate at '\0') */
160 while (*str && strchr(sep, *str))
161 ++str;
163 if (!*str) /* no more tokens */
164 return NULL;
166 token = str;
168 /* skip valid token characters to terminate token and
169 * prepare for the next call (will terminate at '\0)
170 */
171 *last = token + 1;
172 while (**last && !strchr(sep, **last))
173 ++ * last;
175 if (**last) {
176 **last = '\0';
177 ++*last;
178 }
180 return token;
181 }