]> git.saurik.com Git - wxWidgets.git/blob - include/wx/msw/tls.h
0ca7fdfc5e057b5a944574e0ae6563abaa035b43
[wxWidgets.git] / include / wx / msw / tls.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/msw/tls.h
3 // Purpose: Win32 implementation of wxTlsValue<>
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_MSW_TLS_H_
12 #define _WX_MSW_TLS_H_
13
14 #include "wx/msw/wrapwin.h"
15 #include "wx/thread.h"
16 #include "wx/vector.h"
17
18 // ----------------------------------------------------------------------------
19 // wxTlsKey is a helper class encapsulating a TLS slot
20 // ----------------------------------------------------------------------------
21
22 class wxTlsKey
23 {
24 public:
25 // ctor allocates a new key
26 wxTlsKey(wxTlsDestructorFunction destructor)
27 {
28 m_destructor = destructor;
29 m_slot = ::TlsAlloc();
30 }
31
32 // return true if the key was successfully allocated
33 bool IsOk() const { return m_slot != TLS_OUT_OF_INDEXES; }
34
35 // get the key value, there is no error return
36 void *Get() const
37 {
38 return ::TlsGetValue(m_slot);
39 }
40
41 // change the key value, return true if ok
42 bool Set(void *value)
43 {
44 void *old = Get();
45
46 if ( ::TlsSetValue(m_slot, value) == 0 )
47 return false;
48
49 if ( old )
50 m_destructor(old);
51
52 // update m_allValues list of all values - remove old, add new
53 wxCriticalSectionLocker lock(m_csAllValues);
54 if ( old )
55 {
56 for ( wxVector<void*>::iterator i = m_allValues.begin();
57 i != m_allValues.end();
58 ++i )
59 {
60 if ( *i == old )
61 {
62 if ( value )
63 *i = value;
64 else
65 m_allValues.erase(i);
66 return true;
67 }
68 }
69 wxFAIL_MSG( "previous wxTlsKey value not recorded in m_allValues" );
70 }
71
72 if ( value )
73 m_allValues.push_back(value);
74
75 return true;
76 }
77
78 // free the key
79 ~wxTlsKey()
80 {
81 if ( !IsOk() )
82 return;
83
84 // Win32 API doesn't have the equivalent of pthread's destructor, so we
85 // have to keep track of all allocated values and destroy them manually;
86 // ideally we'd do that at thread exit time, but since we could only
87 // do that with wxThread and not otherwise created threads, we do it
88 // here.
89 //
90 // TODO: We should still call destructors for wxTlsKey used in the
91 // thread from wxThread's thread shutdown code, *in addition*
92 // to doing it in ~wxTlsKey.
93 //
94 // NB: No need to lock m_csAllValues, by the time this code is called,
95 // no other thread can be using this key.
96 for ( wxVector<void*>::iterator i = m_allValues.begin();
97 i != m_allValues.end();
98 ++i )
99 {
100 m_destructor(*i);
101 }
102
103 ::TlsFree(m_slot);
104 }
105
106 private:
107 wxTlsDestructorFunction m_destructor;
108 DWORD m_slot;
109
110 wxVector<void*> m_allValues;
111 wxCriticalSection m_csAllValues;
112
113 wxDECLARE_NO_COPY_CLASS(wxTlsKey);
114 };
115
116 #endif // _WX_MSW_TLS_H_
117