aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-09-10 17:26:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-09-10 17:26:55 +0200
commita4dea80c2267f7fccbf62ae4ea3c45b0c7b2c90d (patch)
tree0d0d5d582f6b3a3fb56012d4849aa9daef6feeb4
parent69848e3b70a078a5ba118f0a5ab08e1323954cb2 (diff)
Add low-level once API that is static initialization-safe
-rw-r--r--odb/details/win32/once.cxx6
-rw-r--r--odb/details/win32/once.hxx20
-rw-r--r--odb/details/win32/once.ixx18
-rw-r--r--odb/details/win32/tls.hxx4
-rw-r--r--odb/details/win32/tls.txx12
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);
}