X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/64a044d5a64dd92473b4cc666a6877db78bd37d3..4ed85025f3ba537206f70f3dd10466e16da926d4:/include/wx/msw/tls.h diff --git a/include/wx/msw/tls.h b/include/wx/msw/tls.h index e7dc94023e..0ca7fdfc5e 100644 --- a/include/wx/msw/tls.h +++ b/include/wx/msw/tls.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: wx/unix/tls.h +// Name: wx/msw/tls.h // Purpose: Win32 implementation of wxTlsValue<> // Author: Vadim Zeitlin // Created: 2008-08-08 @@ -11,9 +11,9 @@ #ifndef _WX_MSW_TLS_H_ #define _WX_MSW_TLS_H_ -#include "wx/log.h" - #include "wx/msw/wrapwin.h" +#include "wx/thread.h" +#include "wx/vector.h" // ---------------------------------------------------------------------------- // wxTlsKey is a helper class encapsulating a TLS slot @@ -23,11 +23,10 @@ class wxTlsKey { public: // ctor allocates a new key - wxTlsKey() + wxTlsKey(wxTlsDestructorFunction destructor) { + m_destructor = destructor; m_slot = ::TlsAlloc(); - if ( m_slot == TLS_OUT_OF_INDEXES ) - wxLogError("Creating TLS key failed"); } // return true if the key was successfully allocated @@ -42,31 +41,76 @@ public: // change the key value, return true if ok bool Set(void *value) { - if ( !::TlsSetValue(m_slot, value) ) - { - wxLogSysError(_("Failed to set TLS value")); + 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() ) + 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 ) { - if ( !::TlsFree(m_slot) ) - { - wxLogDebug("TlsFree() failed: %08x", ::GetLastError()); - } + 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_