diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-09-03 16:20:38 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-09-03 16:20:38 +0200 |
commit | 0e2ae18a97fd507bac872031888d34c3a7d8b17b (patch) | |
tree | 3f9a551486969d2bc05f272e2da372c1a55d34cf | |
parent | 137b1eb3e41578d9d4a066ef75c6abfa597c46cd (diff) |
Implement Win32 TLS support
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | m4/static-lib.m4 | 19 | ||||
-rw-r--r-- | odb/Makefile.am | 6 | ||||
-rw-r--r-- | odb/details/config-vc.h | 4 | ||||
-rw-r--r-- | odb/details/config.h.in | 2 | ||||
-rw-r--r-- | odb/details/export.hxx | 18 | ||||
-rw-r--r-- | odb/details/lock.hxx | 17 | ||||
-rw-r--r-- | odb/details/posix/tls.hxx | 3 | ||||
-rw-r--r-- | odb/details/shared-ptr/base.hxx | 4 | ||||
-rw-r--r-- | odb/details/tls.hxx | 28 | ||||
-rw-r--r-- | odb/details/win32/dll.cxx | 52 | ||||
-rw-r--r-- | odb/details/win32/init.cxx | 43 | ||||
-rw-r--r-- | odb/details/win32/init.hxx | 38 | ||||
-rw-r--r-- | odb/details/win32/lock.hxx | 51 | ||||
-rw-r--r-- | odb/details/win32/once-init.hxx | 25 | ||||
-rw-r--r-- | odb/details/win32/once.cxx | 29 | ||||
-rw-r--r-- | odb/details/win32/once.hxx | 49 | ||||
-rw-r--r-- | odb/details/win32/once.ixx | 30 | ||||
-rw-r--r-- | odb/details/win32/tls-init.hxx | 28 | ||||
-rw-r--r-- | odb/details/win32/tls.cxx | 236 | ||||
-rw-r--r-- | odb/details/win32/tls.hxx | 111 | ||||
-rw-r--r-- | odb/details/win32/tls.ixx | 22 | ||||
-rw-r--r-- | odb/details/win32/tls.txx | 87 | ||||
-rw-r--r-- | odb/libodb-vc10.vcxproj | 1 | ||||
-rw-r--r-- | odb/libodb-vc9.vcproj | 1 | ||||
-rw-r--r-- | odb/makefile | 13 |
26 files changed, 872 insertions, 49 deletions
diff --git a/configure.ac b/configure.ac index 041c63e..fe1d59d 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,10 @@ AS_IF([test x$threads = xnone], AC_DEFINE([ODB_THREADS_NONE], [1], [Have no thre AS_IF([test x$threads = xwin32], AC_DEFINE([ODB_THREADS_WIN32], [1], [Have Win32 threads.])) AS_IF([test x$threads = xposix], AC_DEFINE([ODB_THREADS_POSIX], [1], [Have POSIX threads.])) +# Define LIBODB_STATIC_LIB if we are build static library on certain platforms. +# +STATIC_LIB([LIBODB_STATIC_LIB], [Static library interface.]) + # Allow the user to specify the pkgconfig directory. # PKGCONFIG diff --git a/m4/static-lib.m4 b/m4/static-lib.m4 new file mode 100644 index 0000000..1c0af42 --- /dev/null +++ b/m4/static-lib.m4 @@ -0,0 +1,19 @@ +dnl file : m4/static-lib.m4 +dnl author : Boris Kolpackov <boris@codesynthesis.com> +dnl copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +dnl license : GNU GPL v2; see accompanying LICENSE file +dnl +dnl STATIC_LIB(MACRO, DESCRIPTION) +dnl +dnl Define MACRO if we are on MinGW and are only building static library. +dnl +AC_DEFUN([STATIC_LIB], +[ +if test x$enable_shared = xno; then + case $host_os in + mingw*) + AC_DEFINE([$1], [1], [$2]) + ;; + esac +fi +])dnl diff --git a/odb/Makefile.am b/odb/Makefile.am index cfb0af8..afdf450 100644 --- a/odb/Makefile.am +++ b/odb/Makefile.am @@ -18,9 +18,9 @@ nobase_odbinclude_HEADERS += __path__(posix_headers) endif if ODB_THREADS_WIN32 -libodb_la_SOURCES += __path__(win32_sources) +libodb_la_SOURCES += __path__(win32_sources) __path__(win32_dll_sources) nobase_odbinclude_HEADERS += __path__(win32_headers) endif -AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -libodb_la_LDFLAGS = -release __value__(interface_version) +libodb_la_CPPFLAGS= -I$(top_builddir) -I$(top_srcdir) -DLIBODB_DYNAMIC_LIB +libodb_la_LDFLAGS = -release __value__(interface_version) -no-undefined diff --git a/odb/details/config-vc.h b/odb/details/config-vc.h index f90ac4d..52b7430 100644 --- a/odb/details/config-vc.h +++ b/odb/details/config-vc.h @@ -10,8 +10,6 @@ #define ODB_DETAILS_CONFIG_VC_H #define ODB_THREADS_WIN32 -#define ODB_THREADS_TLS_DECLSPEC_POINTER -#define ODB_THREADS_TLS_DECLSPEC_OBJECT - +#define ODB_THREADS_TLS_DECLSPEC #endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/odb/details/config.h.in b/odb/details/config.h.in index aa2417d..a55352a 100644 --- a/odb/details/config.h.in +++ b/odb/details/config.h.in @@ -13,4 +13,6 @@ #undef ODB_THREADS_POSIX #undef ODB_THREADS_WIN32 +#undef LIBODB_STATIC_LIB + #endif /* ODB_DETAILS_CONFIG_H */ diff --git a/odb/details/export.hxx b/odb/details/export.hxx index ef43c6c..19bd313 100644 --- a/odb/details/export.hxx +++ b/odb/details/export.hxx @@ -14,10 +14,22 @@ # define LIBODB_EXPORT #else # ifdef _WIN32 -# ifdef LIBODB_DYNAMIC_LIB -# define LIBODB_EXPORT __declspec(dllexport) +# ifdef _MSC_VER +# ifdef LIBODB_DYNAMIC_LIB +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT __declspec(dllimport) +# endif # else -# define LIBODB_EXPORT __declspec(dllimport) +# ifdef LIBODB_DYNAMIC_LIB +# ifdef DLL_EXPORT +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT +# endif +# else +# define LIBODB_EXPORT __declspec(dllimport) +# endif # endif # else # define LIBODB_EXPORT diff --git a/odb/details/lock.hxx b/odb/details/lock.hxx index 7902d77..b479f28 100644 --- a/odb/details/lock.hxx +++ b/odb/details/lock.hxx @@ -18,30 +18,29 @@ namespace odb struct LIBODB_EXPORT lock { lock (mutex& m) - : mutex_ (m), locked_ (true) + : mutex_ (&m) { - mutex_.lock (); + mutex_->lock (); } ~lock () { - if (locked_) - mutex_.unlock (); + if (mutex_ != 0) + mutex_->unlock (); } void unlock () { - if (locked_) + if (mutex_ != 0) { - mutex_.unlock (); - locked_ = true; + mutex_->unlock (); + mutex_ = 0; } } private: - mutex& mutex_; - bool locked_; + mutex* mutex_; }; } } diff --git a/odb/details/posix/tls.hxx b/odb/details/posix/tls.hxx index 92b0f4b..d23a09a 100644 --- a/odb/details/posix/tls.hxx +++ b/odb/details/posix/tls.hxx @@ -15,9 +15,6 @@ namespace odb namespace details { template <typename T> - class tls; - - template <typename T> class tls { public: diff --git a/odb/details/shared-ptr/base.hxx b/odb/details/shared-ptr/base.hxx index 309f7d2..c8beb07 100644 --- a/odb/details/shared-ptr/base.hxx +++ b/odb/details/shared-ptr/base.hxx @@ -31,8 +31,8 @@ namespace odb char id_; }; - extern share shared; - extern share exclusive; + extern LIBODB_EXPORT share shared; + extern LIBODB_EXPORT share exclusive; } } diff --git a/odb/details/tls.hxx b/odb/details/tls.hxx index 7ce5c19..d2627be 100644 --- a/odb/details/tls.hxx +++ b/odb/details/tls.hxx @@ -50,7 +50,9 @@ namespace odb #elif defined(ODB_THREADS_WIN32) -# ifdef ODB_THREADS_TLS_DECLSPEC_POINTER +# include <odb/details/win32/tls.hxx> + +# ifdef ODB_THREADS_TLS_DECLSPEC # define ODB_TLS_POINTER(type) __declspec(thread) type* namespace odb @@ -74,29 +76,9 @@ namespace odb } # else -# error unsupported TLS pointer model -# endif - -# ifdef ODB_THREADS_TLS_DECLSPEC_OBJECT -# define ODB_TLS_OBJECT(type) __declspec(thread) type - -namespace odb -{ - namespace details - { - template <typename T> - inline T& - tls_get (T& x) - { - return x; - } - } -} - -# else -# error unsupported TLS object model +# define ODB_TLS_POINTER(type) tls<type*> # endif - +# define ODB_TLS_OBJECT(type) tls<type> #else # error unknown threading model #endif diff --git a/odb/details/win32/dll.cxx b/odb/details/win32/dll.cxx new file mode 100644 index 0000000..843be8d --- /dev/null +++ b/odb/details/win32/dll.cxx @@ -0,0 +1,52 @@ +// file : odb/details/win32/dll.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +// If we are building a static library from VC++ (LIBODB_STATIC_LIB) or +// a static library from automake (!DLL_EXPORT), then omit DllMain. +// +#if defined(LIBODB_STATIC_LIB) || !defined (_MSC_VER) && !defined(DLL_EXPORT) + +#include <windows.h> + +#include <odb/details/win32/init.hxx> + +using namespace odb::details; + +extern "C" BOOL WINAPI +DllMain (HINSTANCE, DWORD reason, LPVOID reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + { + process_start (); + thread_start (); + break; + } + + case DLL_THREAD_ATTACH: + { + thread_start (); + break; + } + + case DLL_THREAD_DETACH: + { + thread_end (); + break; + } + + case DLL_PROCESS_DETACH: + { + thread_end (); + process_end (reserved == NULL); + break; + } + } + + return 1; +} + +#endif diff --git a/odb/details/win32/init.cxx b/odb/details/win32/init.cxx new file mode 100644 index 0000000..c07b9d8 --- /dev/null +++ b/odb/details/win32/init.cxx @@ -0,0 +1,43 @@ +// file : odb/details/win32/init.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <odb/details/win32/init.hxx> +#include <odb/details/win32/once-init.hxx> +#include <odb/details/win32/tls-init.hxx> + +namespace odb +{ + namespace details + { + void + process_start () + { + // The order is important. + // + once_process_start (); + tls_process_start (); + } + + void + process_end (bool safe) + { + // The order is important. + // + tls_process_end (safe); + once_process_end (safe); + } + + void + thread_start () + { + } + + void + thread_end () + { + tls_thread_end (); + } + } +} diff --git a/odb/details/win32/init.hxx b/odb/details/win32/init.hxx new file mode 100644 index 0000000..4a49129 --- /dev/null +++ b/odb/details/win32/init.hxx @@ -0,0 +1,38 @@ +// file : odb/details/win32/init.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_INIT_HXX +#define ODB_DETAILS_WIN32_INIT_HXX + +#include <odb/pre.hxx> + +namespace odb +{ + namespace details + { + void + process_start (); + + // The safe parameter indicates whether it is safe to free heap objects. + // If the process is terminated by a call to ExitProcess(), some threads + // might have been killed leaving things in inconsistent state. + // + void + process_end (bool safe = true); + + void + thread_start (); + + // This function may be called even for thread for which thread_start() + // hasn't been called. + // + void + thread_end (); + } +} + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_INIT_HXX diff --git a/odb/details/win32/lock.hxx b/odb/details/win32/lock.hxx new file mode 100644 index 0000000..50611e0 --- /dev/null +++ b/odb/details/win32/lock.hxx @@ -0,0 +1,51 @@ +// file : odb/details/win32/lock.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_LOCK_HXX +#define ODB_DETAILS_WIN32_LOCK_HXX + +#include <odb/pre.hxx> + +#include <windows.h> + +namespace odb +{ + namespace details + { + // Critical section lock. Not exported; for internal use only. + // + struct win32_lock + { + win32_lock (CRITICAL_SECTION& cs) + : cs_ (&cs) + { + EnterCriticalSection (cs_); + } + + ~win32_lock () + { + if (cs_ != 0) + LeaveCriticalSection (cs_); + } + + void + unlock () + { + if (cs_ != 0) + { + LeaveCriticalSection (cs_); + cs_ = 0; + } + } + + private: + CRITICAL_SECTION* cs_; + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_LOCK_HXX diff --git a/odb/details/win32/once-init.hxx b/odb/details/win32/once-init.hxx new file mode 100644 index 0000000..2826a8b --- /dev/null +++ b/odb/details/win32/once-init.hxx @@ -0,0 +1,25 @@ +// file : odb/details/win32/once-init.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_ONCE_INIT_HXX +#define ODB_DETAILS_WIN32_ONCE_INIT_HXX + +#include <odb/pre.hxx> + +namespace odb +{ + namespace details + { + void + once_process_start (); + + void + once_process_end (bool safe); + } +} + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_ONCE_INIT_HXX diff --git a/odb/details/win32/once.cxx b/odb/details/win32/once.cxx new file mode 100644 index 0000000..9201ea6 --- /dev/null +++ b/odb/details/win32/once.cxx @@ -0,0 +1,29 @@ +// file : odb/details/win32/once.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <windows.h> + +#include <odb/details/win32/once.hxx> +#include <odb/details/win32/once-init.hxx> + +namespace odb +{ + namespace details + { + CRITICAL_SECTION once::cs_; + + void + once_process_start () + { + InitializeCriticalSection (&once::cs_); + } + + void + once_process_end (bool) + { + DeleteCriticalSection (&once::cs_); + } + } +} diff --git a/odb/details/win32/once.hxx b/odb/details/win32/once.hxx new file mode 100644 index 0000000..258d5e0 --- /dev/null +++ b/odb/details/win32/once.hxx @@ -0,0 +1,49 @@ +// file : odb/details/win32/once.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_ONCE_HXX +#define ODB_DETAILS_WIN32_ONCE_HXX + +#include <odb/pre.hxx> + +#include <windows.h> + +#include <odb/details/export.hxx> + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT once + { + public: + once (); + + void + call (void (*func) ()); + + private: + once (const once&); + once& operator= (const once&); + + private: + friend void + once_process_start (); + + friend void + once_process_end (bool); + + private: + bool called_; + static CRITICAL_SECTION cs_; + }; + } +} + +#include <odb/details/win32/once.ixx> + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_ONCE_HXX diff --git a/odb/details/win32/once.ixx b/odb/details/win32/once.ixx new file mode 100644 index 0000000..9f1706d --- /dev/null +++ b/odb/details/win32/once.ixx @@ -0,0 +1,30 @@ +// file : odb/details/win32/once.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <odb/details/win32/lock.hxx> + +namespace odb +{ + namespace details + { + inline once:: + once () + : called_ (false) + { + } + + inline void once:: + call (void (*func) ()) + { + win32_lock l (cs_); + + if (!called_) + { + func (); + called_ = true; + } + } + } +} diff --git a/odb/details/win32/tls-init.hxx b/odb/details/win32/tls-init.hxx new file mode 100644 index 0000000..80e00f9 --- /dev/null +++ b/odb/details/win32/tls-init.hxx @@ -0,0 +1,28 @@ +// file : odb/details/win32/tls-init.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_TLS_INIT_HXX +#define ODB_DETAILS_WIN32_TLS_INIT_HXX + +#include <odb/pre.hxx> + +namespace odb +{ + namespace details + { + void + tls_process_start (); + + void + tls_process_end (bool safe); + + void + tls_thread_end (); + } +} + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_TLS_INIT_HXX diff --git a/odb/details/win32/tls.cxx b/odb/details/win32/tls.cxx new file mode 100644 index 0000000..48c2f00 --- /dev/null +++ b/odb/details/win32/tls.cxx @@ -0,0 +1,236 @@ +// file : odb/details/win32/tls.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <windows.h> +#include <winerror.h> // ERROR_INVALID_INDEX + +#include <new> +#include <cstddef> // std::size_t + +#include <odb/details/win32/lock.hxx> +#include <odb/details/win32/tls.hxx> +#include <odb/details/win32/tls-init.hxx> +#include <odb/details/win32/exceptions.hxx> + +using namespace std; + +namespace odb +{ + namespace details + { + typedef void (*dtor_func) (void*); + + struct entry + { + void* value; + dtor_func dtor; + }; + + struct thread_data + { + size_t size; + size_t capacity; + entry entries[0]; + }; + + struct process_data + { + size_t size; + size_t capacity; + dtor_func dtors[0]; + }; + + static DWORD index_ = TLS_OUT_OF_INDEXES; + static CRITICAL_SECTION cs_; + static process_data* proc_data_; + + const size_t init_capacity = 4; + + void + tls_process_start () + { + index_ = TlsAlloc (); + + if (index_ == TLS_OUT_OF_INDEXES) + throw win32_exception (); + + InitializeCriticalSection (&cs_); + + proc_data_ = static_cast<process_data*> ( + operator new ( + sizeof (process_data) + sizeof (dtor_func) * init_capacity)); + + proc_data_->size = 0; + proc_data_->capacity = init_capacity; + memset (proc_data_->dtors, 0, sizeof (dtor_func) * init_capacity); + } + + void + tls_process_end (bool safe) + { + if (safe) + operator delete (proc_data_); + + DeleteCriticalSection (&cs_); + + if (index_ != TLS_OUT_OF_INDEXES) + { + if (!TlsFree (index_)) + throw win32_exception (); + } + } + + void + tls_thread_end () + { + if (thread_data* d = static_cast<thread_data*> (TlsGetValue (index_))) + { + // Call destructors. Implement the pthread semantics in that the + // destructors are called until all the values become 0. + // + for (bool pass (true); pass;) + { + pass = false; + + for (size_t i (0); i < d->size; ++i) + { + if (d->entries[i].dtor != 0 && d->entries[i].value != 0) + { + pass = true; + void* tmp (d->entries[i].value); + d->entries[i].value = 0; + d->entries[i].dtor (tmp); + } + } + } + + operator delete (d); + } + } + + // + // tls_common + // + + std::size_t tls_common:: + _allocate (dtor_func dtor) + { + win32_lock l (cs_); + + size_t n (proc_data_->size); + size_t c (proc_data_->capacity); + + if (n == c) + { + c *= 2; + + process_data* pd ( + static_cast<process_data*> ( + operator new (sizeof (process_data) + sizeof (dtor_func) * c))); + + memcpy (pd->dtors, proc_data_->dtors, n * sizeof (dtor_func)); + memset (proc_data_->dtors + n, 0, sizeof (dtor_func) * (c - n)); + + pd->size = n; + pd->capacity = c; + operator delete (proc_data_); + proc_data_ = pd; + } + + proc_data_->dtors[n] = dtor; + return proc_data_->size++; + } + + void* tls_common:: + _get (std::size_t key) + { + if (thread_data* d = static_cast<thread_data*> (TlsGetValue (index_))) + { + if (key < d->size) + return d->entries[key].value; + } + + // Check if this key is valid. + // + win32_lock l (cs_); + + if (key < proc_data_->size) + return 0; + + throw win32_exception (ERROR_INVALID_INDEX); + } + + void tls_common:: + _set (std::size_t key, void* value) + { + thread_data* d (static_cast<thread_data*> (TlsGetValue (index_))); + + if (d != 0 && key < d->capacity) + { + if (key >= d->size) + { + // Check if this key is valid. If so then we need to copy + // dtors for new slots. + // + win32_lock l (cs_); + + size_t n (proc_data_->size); + + if (key >= n) + throw win32_exception (ERROR_INVALID_INDEX); + + for (size_t i (d->size); i < n; ++i) + d->entries[i].dtor = proc_data_->dtors[i]; + + d->size = n; + } + + d->entries[key].value = value; + } + else + { + // Check if this key is valid. If so then we need to (re)-allocate + // our storage. + // + win32_lock l (cs_); + + size_t n (proc_data_->size); + + if (key >= n) + throw win32_exception (ERROR_INVALID_INDEX); + + size_t c (proc_data_->capacity); + + thread_data* nd ( + static_cast<thread_data*> ( + operator new (sizeof (thread_data) + sizeof (entry) * c))); + + size_t on (d == 0 ? 0 : d->size); + + // Copy over the data. + // + if (on != 0) + memcpy (nd->entries, d->entries, sizeof (entry) * on); + + // Zero out the rest. + // + memset (nd->entries + on, 0, sizeof (entry) * (c - on)); + + // Assign destructors to new slots [on, n). + // + for (size_t i (on); i < n; ++i) + nd->entries[i].dtor = proc_data_->dtors[i]; + + nd->size = n; + nd->capacity = c; + + operator delete (d); + TlsSetValue (index_, nd); + + nd->entries[key].value = value; + } + } + } +} diff --git a/odb/details/win32/tls.hxx b/odb/details/win32/tls.hxx new file mode 100644 index 0000000..b1dce0f --- /dev/null +++ b/odb/details/win32/tls.hxx @@ -0,0 +1,111 @@ +// file : odb/details/win32/tls.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_TLS_HXX +#define ODB_DETAILS_WIN32_TLS_HXX + +#include <odb/pre.hxx> + +#include <cstddef> // std::size_t + +#include <odb/details/export.hxx> +#include <odb/details/win32/once.hxx> + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT tls_common + { + public: + static std::size_t + _allocate (void (*dtor) (void*)); + + static void* + _get (std::size_t key); + + static void + _set (std::size_t key, void* value); + }; + + template <typename T> + class tls: protected tls_common + { + public: + tls (); + + T& + get () const; + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + static void + destructor (void*); + + private: + static once once_; + static std::size_t key_; + }; + + template <typename T> + class tls<T*>: protected tls_common + { + public: + tls (); + + T* + get () const; + + void + set (T* p); + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + private: + static once once_; + static std::size_t key_; + }; + + template <typename T> + inline T& + tls_get (const tls<T>& t) + { + return t.get (); + } + + template <typename T> + inline T* + tls_get (const tls<T*>& t) + { + return t.get (); + } + + template <typename T> + inline void + tls_set (tls<T*>& t, T* p) + { + t.set (p); + } + } +} + +#include <odb/details/win32/tls.ixx> +#include <odb/details/win32/tls.txx> + +#include <odb/post.hxx> + +#endif // ODB_DETAILS_WIN32_TLS_HXX diff --git a/odb/details/win32/tls.ixx b/odb/details/win32/tls.ixx new file mode 100644 index 0000000..7b0f341 --- /dev/null +++ b/odb/details/win32/tls.ixx @@ -0,0 +1,22 @@ +// file : odb/details/win32/tls.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + template <typename T> + inline tls<T>:: + tls () + { + } + + template <typename T> + inline tls<T*>:: + tls () + { + } + } +} diff --git a/odb/details/win32/tls.txx b/odb/details/win32/tls.txx new file mode 100644 index 0000000..f20b6a9 --- /dev/null +++ b/odb/details/win32/tls.txx @@ -0,0 +1,87 @@ +// file : odb/details/win32/tls.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <memory> // std::auto_ptr + +#include <odb/details/win32/exceptions.hxx> + +using namespace std; + +namespace odb +{ + namespace details + { + // tls<T> + // + template <typename T> + once tls<T>::once_; + + template <typename T> + size_t tls<T>::key_; + + template <typename T> + T& tls<T>:: + get () const + { + once_.call (key_init); + void* v (_get (key_)); + + if (v != 0) + return *static_cast<T*> (v); + + auto_ptr<T> p (new T); + _set (key_, p.get ()); + + T& r (*p); + p.release (); + return r; + } + + template <typename T> + void tls<T>:: + key_init () + { + key_ = _allocate (destructor); + } + + template <typename T> + void tls<T>:: + destructor (void* v) + { + delete static_cast<T*> (v); + } + + // tls<T*> + // + template <typename T> + once tls<T*>::once_; + + template <typename T> + size_t tls<T*>::key_; + + template <typename T> + T* tls<T*>:: + get () const + { + once_.call (key_init); + return static_cast<T*> (_get (key_)); + } + + template <typename T> + void tls<T*>:: + set (T* p) + { + once_.call (key_init); + _set (key_, p); + } + + template <typename T> + void tls<T*>:: + key_init () + { + key_ = _allocate (0); + } + } +} diff --git a/odb/libodb-vc10.vcxproj b/odb/libodb-vc10.vcxproj index 81f1a2a..18e5415 100644 --- a/odb/libodb-vc10.vcxproj +++ b/odb/libodb-vc10.vcxproj @@ -165,6 +165,7 @@ __header_entry__(details\config-vc.h) <ItemGroup> __source_entries__(sources) __source_entries__(win32_sources) +__source_entries__(win32_dll_sources) </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/odb/libodb-vc9.vcproj b/odb/libodb-vc9.vcproj index 3877c89..d8a98b3 100644 --- a/odb/libodb-vc9.vcproj +++ b/odb/libodb-vc9.vcproj @@ -342,6 +342,7 @@ > __source_entries__(sources) __source_entries__(win32_sources) +__source_entries__(win32_dll_sources) </Filter> <Filter Name="Header Files" diff --git a/odb/makefile b/odb/makefile index e058463..0fb038d 100644 --- a/odb/makefile +++ b/odb/makefile @@ -26,9 +26,14 @@ details/posix/thread.cxx # Win32-based implementation details. # win32_cxx := \ -details/win32/exceptions.cxx \ +details/win32/init.cxx \ +details/win32/once.cxx \ +details/win32/tls.cxx \ details/win32/condition.cxx \ -details/win32/thread.cxx +details/win32/thread.cxx \ +details/win32/exceptions.cxx + +win32_dll_cxx := details/win32/dll.cxx cxx_tun := $(cxx) $(posix_cxx) cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) @@ -61,6 +66,7 @@ $(out_base)/: $(odb.l) $(dist): export sources := $(cxx) $(dist): export posix_sources := $(posix_cxx) $(dist): export win32_sources := $(win32_cxx) +$(dist): export win32_dll_sources := $(win32_dll_cxx) $(dist): export headers = $(subst $(src_base)/,,$(shell find $(src_base) \ -path $(src_base)/details/posix -a -prune -a -false -o \ @@ -79,7 +85,8 @@ $(dist): export interface_version = $(shell sed -e \ $(dist): $(call dist-data,$(sources) $(posix_sources) $(win32_sources) \ -$(headers) $(posix_headers) $(win32_headers) $(data_dist) details/config.h.in) +$(win32_dll_sources) $(headers) $(posix_headers) $(win32_headers) \ +$(data_dist) details/config.h.in) $(call meta-vc9proj,$(src_base)/libodb-vc9.vcproj) $(call meta-vc10proj,$(src_base)/libodb-vc10.vcxproj) $(call meta-automake) |