]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/msw/tls.h
Reuse wxMessageOutputStderr for wxLogStderr implementation.
[wxWidgets.git] / include / wx / msw / tls.h
index c27271ca6060a3e71a89eba8f907950150dc3e51..0ca7fdfc5e057b5a944574e0ae6563abaa035b43 100644 (file)
@@ -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
@@ -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,19 +41,75 @@ 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<void*>::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<void*>::iterator i = m_allValues.begin();
+              i != m_allValues.end();
+              ++i )
+        {
+            m_destructor(*i);
+        }
+
+        ::TlsFree(m_slot);
     }
 
 private:
+    wxTlsDestructorFunction m_destructor;
     DWORD m_slot;
 
+    wxVector<void*> m_allValues;
+    wxCriticalSection m_csAllValues;
+
     wxDECLARE_NO_COPY_CLASS(wxTlsKey);
 };