X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8b73c5318ccc837aff38c0e5a824bc4fd56c75c8..1d12c6e2be99ae9e7d9a75ba2540ebec7449c92e:/include/wx/msw/tls.h diff --git a/include/wx/msw/tls.h b/include/wx/msw/tls.h index eee0096c97..2ef70a2183 100644 --- a/include/wx/msw/tls.h +++ b/include/wx/msw/tls.h @@ -12,6 +12,8 @@ #define _WX_MSW_TLS_H_ #include "wx/msw/wrapwin.h" +#include "wx/thread.h" +#include "wx/vector.h" // ---------------------------------------------------------------------------- // wxTlsKey is a helper class encapsulating a TLS slot @@ -21,8 +23,9 @@ class wxTlsKey { public: // ctor allocates a new key - wxTlsKey() + wxTlsKey(wxTlsDestructorFunction destructor) { + m_destructor = destructor; m_slot = ::TlsAlloc(); } @@ -38,20 +41,76 @@ public: // change the key value, return true if ok bool Set(void *value) { - return ::TlsSetValue(m_slot, value) != 0; + void *old = Get(); + + if ( ::TlsSetValue(m_slot, value) == 0 ) + return false; + + if ( old ) + m_destructor(old); + + // update m_allValues list of all values - remove old, add new + wxCriticalSectionLocker lock(m_csAllValues); + if ( old ) + { + for ( wxVector::iterator i = m_allValues.begin(); + i != m_allValues.end(); + ++i ) + { + if ( *i == old ) + { + if ( value ) + *i = value; + else + m_allValues.erase(i); + return true; + } + } + wxFAIL_MSG( "previous wxTlsKey value not recorded in m_allValues" ); + } + + if ( value ) + m_allValues.push_back(value); + + return true; } // free the key ~wxTlsKey() { - if ( IsOk() ) - ::TlsFree(m_slot); + if ( !IsOk() ) + return; + + // Win32 API doesn't have the equivalent of pthread's destructor, so we + // have to keep track of all allocated values and destroy them manually; + // ideally we'd do that at thread exit time, but since we could only + // do that with wxThread and not otherwise created threads, we do it + // here. + // + // TODO: We should still call destructors for wxTlsKey used in the + // thread from wxThread's thread shutdown code, *in addition* + // to doing it in ~wxTlsKey. + // + // NB: No need to lock m_csAllValues, by the time this code is called, + // no other thread can be using this key. + for ( wxVector::iterator i = m_allValues.begin(); + i != m_allValues.end(); + ++i ) + { + m_destructor(*i); + } + + ::TlsFree(m_slot); } private: + wxTlsDestructorFunction m_destructor; DWORD m_slot; - DECLARE_NO_COPY_CLASS(wxTlsKey) + wxVector m_allValues; + wxCriticalSection m_csAllValues; + + wxDECLARE_NO_COPY_CLASS(wxTlsKey); }; #endif // _WX_MSW_TLS_H_