Added implementation of thread local storage for OS/2.
[wxWidgets.git] / include / wx / tls.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/tls.h
3 // Purpose: Implementation of thread local storage
4 // Author: Vadim Zeitlin
5 // Created: 2008-08-08
6 // RCS-ID: $Id$
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #ifndef _WX_TLS_H_
12 #define _WX_TLS_H_
13
14 #include "wx/defs.h"
15
16 // ----------------------------------------------------------------------------
17 // check for compiler support of thread-specific variables
18 // ----------------------------------------------------------------------------
19
20 // when not using threads at all, there is no need for thread-specific
21 // values to be really thread-specific
22 #if !wxUSE_THREADS
23 #define wxHAS_COMPILER_TLS
24 #define wxTHREAD_SPECIFIC_DECL
25 // __thread keyword is supported if configure detected it or when using mingw32
26 // >= 4.3 which is known to have it too
27 #elif defined(HAVE___THREAD_KEYWORD) || \
28 (defined(__MINGW32__) && wxCHECK_GCC_VERSION(4, 3))
29 #define wxHAS_COMPILER_TLS
30 #define wxTHREAD_SPECIFIC_DECL __thread
31 // MSVC has its own version which might be supported by some other Windows
32 // compilers, to be tested
33 #elif wxCHECK_VISUALC_VERSION(7)
34 #define wxHAS_COMPILER_TLS
35 #define wxTHREAD_SPECIFIC_DECL __declspec(thread)
36 #endif
37
38 // ----------------------------------------------------------------------------
39 // define wxTLS_TYPE()
40 // ----------------------------------------------------------------------------
41
42 #ifdef wxHAS_COMPILER_TLS
43 #define wxTLS_TYPE(T) wxTHREAD_SPECIFIC_DECL T
44 #define wxTLS_PTR(var) (&(var))
45 #define wxTLS_VALUE(var) (var)
46 #else // !wxHAS_COMPILER_TLS
47 #ifdef __WXMSW__
48 #include "wx/msw/tls.h"
49 #elif defined(__OS2__)
50 #include "wx/os2/tls.h"
51 #elif defined(__UNIX__)
52 #include "wx/unix/tls.h"
53 #else
54 // TODO: we could emulate TLS for such platforms...
55 #error Neither compiler nor OS support thread-specific variables.
56 #endif
57
58 #include <stdlib.h> // for calloc()
59
60 // wxTlsValue<T> represents a thread-specific value of type T but, unlike
61 // with native compiler thread-specific variables, it behaves like a
62 // (never NULL) pointer to T and so needs to be dereferenced before use
63 template <typename T>
64 class wxTlsValue
65 {
66 public:
67 typedef T ValueType;
68
69 // ctor doesn't do anything, the object is created on first access
70 //
71 // FIXME: the thread-specific values are currently not freed under
72 // Windows, resulting in memory leaks, this must be implemented
73 // there somehow (probably by keeping a list of all TLS objects
74 // and cleaning them up in wxThread cleanup)
75 wxTlsValue()
76 #if !defined(__OS2__) && defined(__UNIX__)
77 : m_key(free)
78 #endif
79 {
80 }
81
82 // dtor is only called in the main thread context and so is not enough
83 // to free memory allocated by us for the other threads, we use
84 // destructor function when using Pthreads for this (which is not
85 // called for the main thread as it doesn't call pthread_exit() but
86 // just to be safe we also reset the key anyhow) and simply leak the
87 // memory under Windows (see the FIXME above)
88 ~wxTlsValue()
89 {
90 void * const value = m_key.Get();
91 if ( value)
92 {
93 free(value);
94 m_key.Set(NULL);
95 }
96 }
97
98 // access the object creating it on demand
99 ValueType *Get()
100 {
101 void *value = m_key.Get();
102 if ( !value )
103 {
104 // ValueType must be POD to be used in wxHAS_COMPILER_TLS case
105 // anyhow (at least gcc doesn't accept non-POD values being
106 // declared with __thread) so initialize it as a POD too
107 value = calloc(1, sizeof(ValueType));
108
109 if ( !m_key.Set(value) )
110 {
111 free(value);
112
113 // this will probably result in a crash in the caller but
114 // it's arguably better to crash immediately instead of
115 // slowly dying from out-of-memory errors which would
116 // happen as the next access to this object would allocate
117 // another ValueType instance and so on forever
118 value = NULL;
119 }
120 }
121
122 return static_cast<ValueType *>(value);
123 }
124
125 // pointer-like accessors
126 ValueType *operator->() { return Get(); }
127 ValueType& operator*() { return *Get(); }
128
129 private:
130 wxTlsKey m_key;
131
132 DECLARE_NO_COPY_TEMPLATE_CLASS(wxTlsValue, T)
133 };
134
135 #define wxTLS_TYPE(T) wxTlsValue<T>
136 #define wxTLS_PTR(var) (var)
137 #define wxTLS_VALUE(var) (*(var))
138 #endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS
139
140 #endif // _WX_TLS_H_
141