]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/msw/tls.h
Work around wxNumValidator compilation problems with MSVC 6.
[wxWidgets.git] / include / wx / msw / tls.h
index f946e12bdca5f9432b74ad44038f87ac40004b2e..2ef70a2183cdb826df2e205157881f07fc515b27 100644 (file)
 #ifndef _WX_MSW_TLS_H_
 #define _WX_MSW_TLS_H_
 
-#include "wx/log.h"
-#include "wx/intl.h"
-
 #include "wx/msw/wrapwin.h"
+#include "wx/thread.h"
+#include "wx/vector.h"
 
 // ----------------------------------------------------------------------------
 // wxTlsKey is a helper class encapsulating a TLS slot
@@ -24,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
@@ -43,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<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() )
+        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 )
         {
-            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<void*> m_allValues;
+    wxCriticalSection m_csAllValues;
+
+    wxDECLARE_NO_COPY_CLASS(wxTlsKey);
 };
 
 #endif // _WX_MSW_TLS_H_