X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f35f85a99ceec7ec92b68c84c843b226793107e1..f2049b683752950d1fe91aec07318e7f2122ff16:/include/wx/os2/tls.h diff --git a/include/wx/os2/tls.h b/include/wx/os2/tls.h index adbfadc409..cfe999fe83 100644 --- a/include/wx/os2/tls.h +++ b/include/wx/os2/tls.h @@ -8,10 +8,12 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifndef _WX_MSW_TLS_H_ -#define _WX_MSW_TLS_H_ +#ifndef _WX_OS2_TLS_H_ +#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,11 +23,12 @@ 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; + if (rc != NO_ERROR) + m_slot = NULL; } // return true if the key was successfully allocated @@ -40,22 +43,76 @@ public: // change the key value, return true if ok bool Set(void *value) { + void *old = Get(); + m_slot = (ULONG*)value; - return true; + + 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; - DECLARE_NO_COPY_CLASS(wxTlsKey) + wxVector m_allValues; + wxCriticalSection m_csAllValues; + + wxDECLARE_NO_COPY_CLASS(wxTlsKey); }; -#endif // _WX_MSW_TLS_H_ +#endif // _WX_OS2_TLS_H_