diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-09-10 17:26:55 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-09-10 17:26:55 +0200 |
commit | a4dea80c2267f7fccbf62ae4ea3c45b0c7b2c90d (patch) | |
tree | 0d0d5d582f6b3a3fb56012d4849aa9daef6feeb4 | |
parent | 69848e3b70a078a5ba118f0a5ab08e1323954cb2 (diff) |
Add low-level once API that is static initialization-safe
-rw-r--r-- | odb/details/win32/once.cxx | 6 | ||||
-rw-r--r-- | odb/details/win32/once.hxx | 20 | ||||
-rw-r--r-- | odb/details/win32/once.ixx | 18 | ||||
-rw-r--r-- | odb/details/win32/tls.hxx | 4 | ||||
-rw-r--r-- | 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<T> // template <typename T> - once tls<T>::once_; + win32_once_t tls<T>::once_= WIN32_ONCE_INIT; template <typename T> size_t tls<T>::key_; @@ -25,7 +25,7 @@ namespace odb T& tls<T>:: get () const { - once_.call (key_init); + win32_once (once_, key_init); if (void* v = _get (key_)) return *static_cast<T*> (v); @@ -42,7 +42,7 @@ namespace odb void tls<T>:: free () { - once_.call (key_init); + win32_once (once_, key_init); if (void* v = _get (key_)) { @@ -68,7 +68,7 @@ namespace odb // tls<T*> // template <typename T> - once tls<T*>::once_; + win32_once_t tls<T*>::once_ = WIN32_ONCE_INIT; template <typename T> size_t tls<T*>::key_; @@ -77,7 +77,7 @@ namespace odb T* tls<T*>:: get () const { - once_.call (key_init); + win32_once (once_, key_init); return static_cast<T*> (_get (key_)); } @@ -85,7 +85,7 @@ namespace odb void tls<T*>:: set (T* p) { - once_.call (key_init); + win32_once (once_, key_init); _set (key_, p); } |