prepare for the release of rrdtool-1.2.9
[rrdtool.git] / src / rrd_thread_safe_nt.c
1 /*****************************************************************************
2  * RRDtool 1.2.9  Copyright by Tobi Oetiker, 1997-2005
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  *************************************************************************** */
12
13 #include <windows.h>
14 #include <string.h>
15 /* #include <error.h> */
16 #include "rrd.h"
17 #include "rrd_tool.h"
18
19 /* Key for the thread-specific rrd_context */
20 static DWORD context_key;
21 static CRITICAL_SECTION CriticalSection; 
22
23
24 /* Once-only initialisation of the key */
25 static DWORD context_key_once = 0;
26
27
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;
47                 
48         context_init_context();
49  
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();
61
62         ctx = rrd_get_context();
63
64     EnterCriticalSection(&CriticalSection); 
65     strncpy(ctx->lib_errstr, strerror(err), ctx->errlen);
66         LeaveCriticalSection(&CriticalSection); 
67
68     return ctx->lib_errstr;
69 }
70 /*
71  * there much be a re-entrant version of these somewhere in win32 land
72  */
73 struct tm* localtime_r(const time_t *timep, struct tm* result)
74 {
75         struct tm *local;
76         context_init_context();
77
78         EnterCriticalSection(&CriticalSection);
79         local = localtime(timep);
80         memcpy(result,local,sizeof(struct tm));
81         LeaveCriticalSection(&CriticalSection);
82         return result;
83 }
84 char* ctime_r(const time_t *timep, char* result)
85 {
86         char *local;
87         context_init_context();
88
89         EnterCriticalSection(&CriticalSection);
90         local = ctime(timep);
91         strcpy(result,local);
92         LeaveCriticalSection(&CriticalSection);
93         return result;
94 }
95
96 struct tm* gmtime_r(const time_t *timep, struct tm* result)
97 {
98         struct tm *local;
99         context_init_context();
100
101         EnterCriticalSection(&CriticalSection);
102         local = gmtime(timep);
103         memcpy(result,local,sizeof(struct tm));
104         LeaveCriticalSection(&CriticalSection);
105         return result;
106 }
107
108 /* implementation from Apache's APR library */
109 char *strtok_r(char *str, const char *sep, char **last)
110 {
111     char *token;
112         context_init_context();
113
114
115     if (!str)           /* subsequent call */
116         str = *last;    /* start where we left off */
117
118     /* skip characters in sep (will terminate at '\0') */
119     while (*str && strchr(sep, *str))
120         ++str;
121
122     if (!*str)          /* no more tokens */
123         return NULL;
124
125     token = str;
126
127     /* skip valid token characters to terminate token and
128      * prepare for the next call (will terminate at '\0) 
129      */
130     *last = token + 1;
131     while (**last && !strchr(sep, **last))
132         ++*last;
133
134     if (**last) {
135         **last = '\0';
136         ++*last;
137     }
138
139     return token;
140 }
141