]> git.saurik.com Git - wxWidgets.git/blame - include/wx/tls.h
Use explicit wxPGPropertyFlags enum type with wxPGProperty::SetFlag() and similar...
[wxWidgets.git] / include / wx / tls.h
CommitLineData
64a044d5
VZ
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
8b73c531
VZ
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))
64a044d5
VZ
29 #define wxHAS_COMPILER_TLS
30 #define wxTHREAD_SPECIFIC_DECL __thread
8b73c531
VZ
31// MSVC has its own version which might be supported by some other Windows
32// compilers, to be tested
64a044d5
VZ
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
8b73c531
VZ
44 #define wxTLS_PTR(var) (&(var))
45 #define wxTLS_VALUE(var) (var)
64a044d5 46#else // !wxHAS_COMPILER_TLS
49e714e1
VS
47
48 extern "C"
49 {
50 typedef void (*wxTlsDestructorFunction)(void*);
51 }
52
53 #if defined(__WXMSW__)
64a044d5 54 #include "wx/msw/tls.h"
f35f85a9
SN
55 #elif defined(__OS2__)
56 #include "wx/os2/tls.h"
64a044d5
VZ
57 #elif defined(__UNIX__)
58 #include "wx/unix/tls.h"
59 #else
60 // TODO: we could emulate TLS for such platforms...
61 #error Neither compiler nor OS support thread-specific variables.
62 #endif
63
8b73c531
VZ
64 #include <stdlib.h> // for calloc()
65
66 // wxTlsValue<T> represents a thread-specific value of type T but, unlike
67 // with native compiler thread-specific variables, it behaves like a
68 // (never NULL) pointer to T and so needs to be dereferenced before use
49e714e1
VS
69 //
70 // Note: T must be a POD!
71 //
72 // Note: On Unix, thread-specific T value is freed when the thread exits.
73 // On Windows, thread-specific values are freed later, when given
74 // wxTlsValue<T> is destroyed. The only exception to this is the
75 // value for the main thread, which is always freed when
76 // wxTlsValue<T> is destroyed.
64a044d5
VZ
77 template <typename T>
78 class wxTlsValue
79 {
80 public:
81 typedef T ValueType;
82
8b73c531 83 // ctor doesn't do anything, the object is created on first access
49e714e1 84 wxTlsValue() : m_key(free) {}
64a044d5 85
8b73c531
VZ
86 // dtor is only called in the main thread context and so is not enough
87 // to free memory allocated by us for the other threads, we use
88 // destructor function when using Pthreads for this (which is not
89 // called for the main thread as it doesn't call pthread_exit() but
49e714e1 90 // just to be safe we also reset the key anyhow)
8b73c531 91 ~wxTlsValue()
64a044d5 92 {
49e714e1
VS
93 if ( m_key.Get() )
94 m_key.Set(NULL); // this deletes the value
8b73c531 95 }
64a044d5 96
8b73c531
VZ
97 // access the object creating it on demand
98 ValueType *Get()
99 {
100 void *value = m_key.Get();
101 if ( !value )
102 {
103 // ValueType must be POD to be used in wxHAS_COMPILER_TLS case
104 // anyhow (at least gcc doesn't accept non-POD values being
105 // declared with __thread) so initialize it as a POD too
106 value = calloc(1, sizeof(ValueType));
107
108 if ( !m_key.Set(value) )
109 {
110 free(value);
111
112 // this will probably result in a crash in the caller but
113 // it's arguably better to crash immediately instead of
114 // slowly dying from out-of-memory errors which would
115 // happen as the next access to this object would allocate
116 // another ValueType instance and so on forever
117 value = NULL;
118 }
119 }
120
121 return static_cast<ValueType *>(value);
64a044d5
VZ
122 }
123
8b73c531
VZ
124 // pointer-like accessors
125 ValueType *operator->() { return Get(); }
126 ValueType& operator*() { return *Get(); }
64a044d5
VZ
127
128 private:
129 wxTlsKey m_key;
130
131 DECLARE_NO_COPY_TEMPLATE_CLASS(wxTlsValue, T)
132 };
133
134 #define wxTLS_TYPE(T) wxTlsValue<T>
8b73c531
VZ
135 #define wxTLS_PTR(var) (var)
136 #define wxTLS_VALUE(var) (*(var))
64a044d5
VZ
137#endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS
138
139#endif // _WX_TLS_H_
140