X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c0c133e13b36a923c65f94499554e432bc3a0daa..d642db66a5efc82d374b813022c72ba88bc50839:/include/wx/os2/tls.h diff --git a/include/wx/os2/tls.h b/include/wx/os2/tls.h index 4c22721fb3..cfe999fe83 100644 --- a/include/wx/os2/tls.h +++ b/include/wx/os2/tls.h @@ -12,6 +12,8 @@ #define _WX_OS2_TLS_H_ #include "wx/os2/private.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; APIRET rc = ::DosAllocThreadLocalMemory(1, &m_slot); if (rc != NO_ERROR) m_slot = NULL; @@ -40,20 +43,74 @@ public: // change the key value, return true if ok bool Set(void *value) { + void *old = Get(); + m_slot = (ULONG*)value; + + 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() ) - ::DosFreeThreadLocalMemory(m_slot); + if ( !IsOk() ) + return; + + // Win32 and OS/2 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); + } + + ::DosFreeThreadLocalMemory(m_slot); } private: + wxTlsDestructorFunction m_destructor; ULONG* m_slot; + wxVector m_allValues; + wxCriticalSection m_csAllValues; + wxDECLARE_NO_COPY_CLASS(wxTlsKey); };