From a4dea80c2267f7fccbf62ae4ea3c45b0c7b2c90d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 10 Sep 2010 17:26:55 +0200 Subject: Add low-level once API that is static initialization-safe --- odb/details/win32/once.cxx | 6 +++--- odb/details/win32/once.hxx | 20 ++++++++++++-------- odb/details/win32/once.ixx | 18 ++++++++++++++++-- odb/details/win32/tls.hxx | 4 ++-- odb/details/win32/tls.txx | 12 ++++++------ 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/odb/details/win32/once.cxx b/odb/details/win32/once.cxx index 0125d23..33523c3 100644 --- a/odb/details/win32/once.cxx +++ b/odb/details/win32/once.cxx @@ -16,18 +16,18 @@ namespace odb { namespace details { - CRITICAL_SECTION once::cs_; + CRITICAL_SECTION win32_once_cs_; void once_process_start () { - InitializeCriticalSection (&once::cs_); + InitializeCriticalSection (&win32_once_cs_); } void once_process_end (bool) { - DeleteCriticalSection (&once::cs_); + DeleteCriticalSection (&win32_once_cs_); } } } diff --git a/odb/details/win32/once.hxx b/odb/details/win32/once.hxx index 05bdca2..c6c31f6 100644 --- a/odb/details/win32/once.hxx +++ b/odb/details/win32/once.hxx @@ -35,16 +35,20 @@ namespace odb once& operator= (const once&); private: - friend void - once_process_start (); - - friend void - once_process_end (bool); - - private: bool called_; - static CRITICAL_SECTION cs_; }; + + // Low-level, POSIX-like API that can be used safely during static + // initialization (that is, win32_once() can be called during static + // initialization) provided once_process_start() has been called. + // + typedef unsigned int win32_once_t; + const win32_once_t WIN32_ONCE_INIT = 0; + + LIBODB_EXPORT void + win32_once (win32_once_t&, void (*func) ()); + + extern LIBODB_EXPORT CRITICAL_SECTION win32_once_cs_; } } diff --git a/odb/details/win32/once.ixx b/odb/details/win32/once.ixx index 9f1706d..de46371 100644 --- a/odb/details/win32/once.ixx +++ b/odb/details/win32/once.ixx @@ -9,6 +9,19 @@ namespace odb { namespace details { + inline void + win32_once (win32_once_t& o, void (*func) ()) + { + win32_lock l (win32_once_cs_); + + if (o == 0) + { + o = 1; + l.unlock (); + func (); + } + } + inline once:: once () : called_ (false) @@ -18,12 +31,13 @@ namespace odb inline void once:: call (void (*func) ()) { - win32_lock l (cs_); + win32_lock l (win32_once_cs_); if (!called_) { - func (); called_ = true; + l.unlock (); + func (); } } } diff --git a/odb/details/win32/tls.hxx b/odb/details/win32/tls.hxx index 3354723..3dcb571 100644 --- a/odb/details/win32/tls.hxx +++ b/odb/details/win32/tls.hxx @@ -54,7 +54,7 @@ namespace odb destructor (void*); private: - static once once_; + static win32_once_t once_; static std::size_t key_; }; @@ -79,7 +79,7 @@ namespace odb key_init (); private: - static once once_; + static win32_once_t once_; static std::size_t key_; }; diff --git a/odb/details/win32/tls.txx b/odb/details/win32/tls.txx index 025e7cb..4290a35 100644 --- a/odb/details/win32/tls.txx +++ b/odb/details/win32/tls.txx @@ -16,7 +16,7 @@ namespace odb // tls // template - once tls::once_; + win32_once_t tls::once_= WIN32_ONCE_INIT; template size_t tls::key_; @@ -25,7 +25,7 @@ namespace odb T& tls:: get () const { - once_.call (key_init); + win32_once (once_, key_init); if (void* v = _get (key_)) return *static_cast (v); @@ -42,7 +42,7 @@ namespace odb void tls:: free () { - once_.call (key_init); + win32_once (once_, key_init); if (void* v = _get (key_)) { @@ -68,7 +68,7 @@ namespace odb // tls // template - once tls::once_; + win32_once_t tls::once_ = WIN32_ONCE_INIT; template size_t tls::key_; @@ -77,7 +77,7 @@ namespace odb T* tls:: get () const { - once_.call (key_init); + win32_once (once_, key_init); return static_cast (_get (key_)); } @@ -85,7 +85,7 @@ namespace odb void tls:: set (T* p) { - once_.call (key_init); + win32_once (once_, key_init); _set (key_, p); } -- cgit v1.1