Code

Imported upstream version 1.3.8.
[pkg-rrdtool.git] / src / rrd_thread_safe_nt.c
1 /*****************************************************************************
2  * RRDtool 1.3.8  Copyright by Tobi Oetiker, 1997-2009
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 1801 2009-05-19 13:45:05Z 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 volatile LONG 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(&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 }
62 #ifdef WIN32
63         rrd_context_t *rrd_force_new_context(void)
64         {
65                 rrd_context_t *ctx;
67                 context_init_context();
69                 ctx = rrd_new_context();
70                 TlsSetValue(context_key, ctx);
72                 return ctx;
73         }
74 #endif
76 #undef strerror
77 const char *rrd_strerror(
78     int err)
79 {
80     rrd_context_t *ctx;
82     context_init_context();
84     ctx = rrd_get_context();
86     EnterCriticalSection(&CriticalSection);
87     strncpy(ctx->lib_errstr, strerror(err), sizeof(ctx->lib_errstr));
88     ctx->lib_errstr[sizeof(ctx->lib_errstr) - 1] = '\0';
89     LeaveCriticalSection(&CriticalSection);
91     return ctx->lib_errstr;
92 }
94 /*
95  * there much be a re-entrant version of these somewhere in win32 land
96  */
97 struct tm *localtime_r(
98     const time_t *timep,
99     struct tm *result)
101     struct tm *local;
103     context_init_context();
105     EnterCriticalSection(&CriticalSection);
106     local = localtime(timep);
107     memcpy(result, local, sizeof(struct tm));
108     LeaveCriticalSection(&CriticalSection);
109     return result;
112 char     *ctime_r(
113     const time_t *timep,
114     char *result)
116     char     *local;
118     context_init_context();
120     EnterCriticalSection(&CriticalSection);
121     local = ctime(timep);
122     strcpy(result, local);
123     LeaveCriticalSection(&CriticalSection);
124     return result;
127 struct tm *gmtime_r(
128     const time_t *timep,
129     struct tm *result)
131     struct tm *local;
133     context_init_context();
135     EnterCriticalSection(&CriticalSection);
136     local = gmtime(timep);
137     memcpy(result, local, sizeof(struct tm));
138     LeaveCriticalSection(&CriticalSection);
139     return result;
142 /* implementation from Apache's APR library */
143 char     *strtok_r(
144     char *str,
145     const char *sep,
146     char **last)
148     char     *token;
150     context_init_context();
153     if (!str)           /* subsequent call */
154         str = *last;    /* start where we left off */
156     /* skip characters in sep (will terminate at '\0') */
157     while (*str && strchr(sep, *str))
158         ++str;
160     if (!*str)          /* no more tokens */
161         return NULL;
163     token = str;
165     /* skip valid token characters to terminate token and
166      * prepare for the next call (will terminate at '\0) 
167      */
168     *last = token + 1;
169     while (**last && !strchr(sep, **last))
170         ++ * last;
172     if (**last) {
173         **last = '\0';
174         ++*last;
175     }
177     return token;