It uses lots of global vars. You may use it in functions not
designed to be thread-safe like functions wrapping the _r version of some
operation (eg. rrd_create, but not in rrd_create_r)
-
+
+WIN32 Platform Note (added 04/01/03):
+
+Both rrdtool.vcproj (MSVC++ 7.0) and rrd.dsw (MSVC++ 6.0) are configured to compile with rrd_thread_safe_nt.c.
'INC' => '-I../../src/ -I../../libraries/freetype-2.0.5/include -I ../../libraries/libart_lgpl-2.3.7 -I ../../libraries/zlib-1.1.4 -I ../../libraries/libpng-1.2.0',
'OPTIMIZE' => '-O2 -MT',
# change this path to refer to your libc.lib
- 'MYEXTLIB' => '"$(VCINSTALLDIR)/vc7/lib/libcmt.lib" ../../src/debug/rrd.lib ../../libraries/libart_lgpl-2.3.7/debug/libart.lib ../../libraries/zlib-1.1.4/debug/zlib.lib ../../libraries/libpng-1.2.0/debug/png.lib ../../libraries/freetype-2.0.5/debug/freetype.lib',
+# keep one line for MSVC++ 6.0 and one for 7.0
+ 'MYEXTLIB' => '"' . $ENV{'MSVCDir'} . '/lib/libc.lib" ../../src/release/rrd.lib ../../libraries/libart_lgpl-2.3.7/release/libart.lib ../../libraries/zlib-1.1.4/release/zlib.lib ../../libraries/libpng-1.2.0/release/png.lib ../../libraries/freetype-2.0.5/release/freetype.lib',
# 'MYEXTLIB' => '"$(VCINSTALLDIR)/vc7/lib/libcmt.lib" ../../src/release/rrd.lib ../../libraries/libart_lgpl-2.3.7/release/libart.lib ../../libraries/zlib-1.1.4/release/zlib.lib ../../libraries/libpng-1.2.0\release\png.lib ../../libraries/freetype-2.0.5/release/freetype.lib',
'realclean' => {FILES => 't/demo?.rrd t/demo?.png' },
($] ge '5.005') ? (
# End Source File
# Begin Source File
+SOURCE=.\rrd_nan_inf.c
+# End Source File
+# Begin Source File
+
SOURCE=.\rrd_open.c
# End Source File
# Begin Source File
# End Source File
# Begin Source File
+SOURCE=.\rrd_thread_safe_nt.c
+# End Source File
+# Begin Source File
+
SOURCE=.\rrd_tune.c
# End Source File
# Begin Source File
*****************************************************************************
* $Id$
* $Log$
+ * Revision 1.4 2003/04/01 22:52:23 jake
+ * Fix Win32 build. VC++ 6.0 and 7.0 now use the thread-safe code.
+ *
* Revision 1.3 2003/02/13 07:05:27 oetiker
* Find attached the patch I promised to send to you. Please note that there
* are three new source files (src/rrd_is_thread_safe.h, src/rrd_thread_safe.c
int argc, char **argv);
/* NOTE: rrd_update_r is only thread-safe if no at-style time
specifications get used!!! */
-int rrd_update_r(char *filename, char *template,
+int rrd_update_r(char *filename, char *_template,
int argc, char **argv);
int rrd_dump_r(char *filename);
time_t rrd_last_r(char *filename);
Optimization="0"
AdditionalIncludeDirectories="..\libraries\libpng-1.2.0,..\libraries\zlib-1.1.4,..\libraries\libart_lgpl-2.3.7,..\libraries\freetype-2.0.5\include"
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_CTYPE_DISABLE_MACROS"
- RuntimeLibrary="4"
+ RuntimeLibrary="1"
PrecompiledHeaderFile=".\debug/rrd.pch"
AssemblerListingLocation=".\debug/"
ObjectFile=".\debug/"
RelativePath=".\rrd_last.c">
</File>
<File
+ RelativePath="rrd_nan_inf.c">
+ </File>
+ <File
RelativePath=".\rrd_open.c">
</File>
<File
RelativePath=".\rrd_rpncalc.c">
</File>
<File
+ RelativePath="rrd_thread_safe_nt.c">
+ </File>
+ <File
RelativePath=".\rrd_tune.c">
</File>
<File
#ifndef RRD_DEFAULT_FONT
#ifdef WIN32
-#define RRD_DEFAULT_FONT "c:/winnt/fonts/COUR.TTF"
+/* this is set in confignt/config.h */
#else
#define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/openoffice/ariosor.ttf"
/* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/Arial.ttf" */
#if defined(WIN32)
+#include <math.h>
+
double set_to_DNAN(void) { return (double)fmod(0.0,0.0); }
double set_to_DINF(void) { return (double)fabs((double)log(0.0)); }
#include "rrd_tool.h"
#define MAXLEN 4096
#define ERRBUFLEN 256
+
static char rrd_error[MAXLEN] = "\0";
static char rrd_liberror[ERRBUFLEN] = "\0";
/* The global context is very useful in the transition period to even
--- /dev/null
+/*****************************************************************************
+ * RRDtool 1.1.x Copyright Tobias Oetiker, 1997 - 2002
+ * This file: Copyright 2003 Peter Stamfest <peter@stamfest.at>
+ * & Tobias Oetiker
+ * Distributed under the GPL
+ *****************************************************************************
+ * rrd_thread_safe.c Contains routines used when thread safety is required
+ * for win32
+ *****************************************************************************
+ * $Id$
+ *************************************************************************** */
+
+#include <windows.h>
+#include <string.h>
+/* #include <error.h> */
+#include "rrd.h"
+#include "rrd_tool.h"
+
+/* Key for the thread-specific rrd_context */
+static DWORD context_key;
+static CRITICAL_SECTION CriticalSection;
+
+
+/* Once-only initialisation of the key */
+static DWORD context_key_once = 0;
+
+
+/* Free the thread-specific rrd_context - we might actually use
+ rrd_free_context instead...
+ */
+static void context_destroy_context(void)
+{
+ DeleteCriticalSection(&CriticalSection);
+ TlsFree(context_key);
+ context_key_once=0;
+}
+static void context_init_context(void)
+{
+ if (!InterlockedExchange(&context_key_once, 1)) {
+ context_key = TlsAlloc();
+ InitializeCriticalSection(&CriticalSection);
+ atexit(context_destroy_context);
+ }
+}
+struct rrd_context *rrd_get_context(void) {
+ struct rrd_context *ctx;
+
+ context_init_context();
+
+ ctx = TlsGetValue(context_key);
+ if (!ctx) {
+ ctx = rrd_new_context();
+ TlsSetValue(context_key, ctx);
+ }
+ return ctx;
+}
+#undef strerror
+const char *rrd_strerror(int err) {
+ struct rrd_context *ctx;
+ context_init_context();
+
+ ctx = rrd_get_context();
+
+ EnterCriticalSection(&CriticalSection);
+ strncpy(ctx->lib_errstr, strerror(err), ctx->errlen);
+ LeaveCriticalSection(&CriticalSection);
+
+ return ctx->lib_errstr;
+}
+/*
+ * there much be a re-entrant version of these somewhere in win32 land
+ */
+struct tm* localtime_r(const time_t *timep, struct tm* result)
+{
+ struct tm *local;
+ context_init_context();
+
+ EnterCriticalSection(&CriticalSection);
+ local = localtime(timep);
+ memcpy(result,local,sizeof(struct tm));
+ LeaveCriticalSection(&CriticalSection);
+ return result;
+}
+char* ctime_r(const time_t *timep, char* result)
+{
+ char *local;
+ context_init_context();
+
+ EnterCriticalSection(&CriticalSection);
+ local = ctime(timep);
+ strcpy(result,local);
+ LeaveCriticalSection(&CriticalSection);
+ return result;
+}
+
+struct tm* gmtime_r(const time_t *timep, struct tm* result)
+{
+ struct tm *local;
+ context_init_context();
+
+ EnterCriticalSection(&CriticalSection);
+ local = gmtime(timep);
+ memcpy(result,local,sizeof(struct tm));
+ LeaveCriticalSection(&CriticalSection);
+ return result;
+}
+
+/* implementation from Apache's APR library */
+char *strtok_r(char *str, const char *sep, char **last)
+{
+ char *token;
+ context_init_context();
+
+
+ if (!str) /* subsequent call */
+ str = *last; /* start where we left off */
+
+ /* skip characters in sep (will terminate at '\0') */
+ while (*str && strchr(sep, *str))
+ ++str;
+
+ if (!*str) /* no more tokens */
+ return NULL;
+
+ token = str;
+
+ /* skip valid token characters to terminate token and
+ * prepare for the next call (will terminate at '\0)
+ */
+ *last = token + 1;
+ while (**last && !strchr(sep, **last))
+ ++*last;
+
+ if (**last) {
+ **last = '\0';
+ ++*last;
+ }
+
+ return token;
+}
+
#define isnan _isnan
#define finite _finite
#define isinf(a) (_fpclass(a) == _FPCLASS_NINF || _fpclass(a) == _FPCLASS_PINF)
+struct tm* localtime_r(const time_t *timep, struct tm* result);
+char* ctime_r(const time_t *timep, char* result);
+struct tm* gmtime_r(const time_t *timep, struct tm* result);
+char *strtok_r(char *str, const char *sep, char **last);
#endif
/* local include files -- need to be after the system ones */
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /I "..\libraries\libpng-1.2.0" /I "..\libraries\zlib-1.1.4" /I "..\libraries\libart_lgpl-2.3.7" /I "..\libraries\freetype-2.0.5\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /I "..\libraries\libpng-1.2.0" /I "..\libraries\zlib-1.1.4" /I "..\libraries\libart_lgpl-2.3.7" /I "..\libraries\freetype-2.0.5\include" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /D MAKE_TIMESTAMP=\"WIN32\" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x100c /d "NDEBUG"
# ADD RSC /l 0x100c /d "NDEBUG"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\libraries\libpng-1.2.0" /I "..\libraries\zlib-1.1.4" /I "..\libraries\libart_lgpl-2.3.7" /I "..\libraries\freetype-2.0.5\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FR /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\libraries\libpng-1.2.0" /I "..\libraries\zlib-1.1.4" /I "..\libraries\libart_lgpl-2.3.7" /I "..\libraries\freetype-2.0.5\include" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /D MAKE_TIMESTAMP=\"WIN32\" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x100c /d "_DEBUG"
# ADD RSC /l 0x100c /d "_DEBUG"