]> git.saurik.com Git - wxWidgets.git/blame - include/wx/msw/tls.h
Free calloc()'d pointer correctly in wxFSWatchEntryMSW.
[wxWidgets.git] / include / wx / msw / tls.h
CommitLineData
64a044d5 1///////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: wx/msw/tls.h
64a044d5
VZ
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
64a044d5 14#include "wx/msw/wrapwin.h"
49e714e1
VS
15#include "wx/thread.h"
16#include "wx/vector.h"
64a044d5
VZ
17
18// ----------------------------------------------------------------------------
19// wxTlsKey is a helper class encapsulating a TLS slot
20// ----------------------------------------------------------------------------
21
22class wxTlsKey
23{
24public:
25 // ctor allocates a new key
49e714e1 26 wxTlsKey(wxTlsDestructorFunction destructor)
64a044d5 27 {
49e714e1 28 m_destructor = destructor;
64a044d5 29 m_slot = ::TlsAlloc();
64a044d5
VZ
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 {
49e714e1
VS
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;
64a044d5
VZ
76 }
77
78 // free the key
79 ~wxTlsKey()
80 {
49e714e1
VS
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);
64a044d5
VZ
104 }
105
106private:
49e714e1 107 wxTlsDestructorFunction m_destructor;
64a044d5
VZ
108 DWORD m_slot;
109
49e714e1
VS
110 wxVector<void*> m_allValues;
111 wxCriticalSection m_csAllValues;
112
c0c133e1 113 wxDECLARE_NO_COPY_CLASS(wxTlsKey);
64a044d5
VZ
114};
115
116#endif // _WX_MSW_TLS_H_
117