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