]> git.saurik.com Git - wxWidgets.git/commitdiff
Deallocate wxThreadSpecificInfo when wxThread ends.
authorVáclav Slavík <vslavik@fastmail.fm>
Wed, 18 Sep 2013 16:03:25 +0000 (16:03 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Wed, 18 Sep 2013 16:03:25 +0000 (16:03 +0000)
Cleanup wxThreadSpecificInfo after wxThread::Entry returns to be more
memory efficient.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74834 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/private/threadinfo.h
include/wx/thread.h
include/wx/thrimpl.cpp
src/common/threadinfo.cpp
src/gtk1/threadsgi.cpp
src/msw/thread.cpp
src/os2/thread.cpp
src/osx/carbon/thread.cpp
src/unix/threadpsx.cpp

index 1ff241bda863d033993fc8fe78426f53dc831f9b..27a71674b0624e2cfddb32036cf44be4ae4bce2d 100644 (file)
@@ -52,6 +52,13 @@ public:
     wxLocaleUntranslatedStrings untranslatedStrings;
 #endif
 
     wxLocaleUntranslatedStrings untranslatedStrings;
 #endif
 
+#if wxUSE_THREADS
+    // Cleans up storage for the current thread. Should be called when a thread
+    // is being destroyed. If it's not called, the only bad thing that happens
+    // is that the memory is deallocated later, on process termination.
+    static void ThreadCleanUp();
+#endif
+
 private:
     wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {}
 };
 private:
     wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {}
 };
index 086007f82623a10382460acaf9cabc8fcaa2e4af..6806d82feafab53f6304c11f28993470bed7bff4 100644 (file)
@@ -614,6 +614,8 @@ protected:
     // of this thread.
     virtual void *Entry() = 0;
 
     // of this thread.
     virtual void *Entry() = 0;
 
+    // use this to call the Entry() virtual method
+    void *CallEntry();
 
     // Callbacks which may be overridden by the derived class to perform some
     // specific actions when the thread is deleted or killed. By default they
 
     // Callbacks which may be overridden by the derived class to perform some
     // specific actions when the thread is deleted or killed. By default they
index 737ff85fa1328b96113335aea3a5af74c35f447c..000b24d589b4610cae8fad02c7a26492813bf3fb 100644 (file)
@@ -342,8 +342,16 @@ wxSemaError wxSemaphore::Post()
 // ----------------------------------------------------------------------------
 
 #include "wx/utils.h"
 // ----------------------------------------------------------------------------
 
 #include "wx/utils.h"
+#include "wx/private/threadinfo.h"
+#include "wx/scopeguard.h"
 
 void wxThread::Sleep(unsigned long milliseconds)
 {
     wxMilliSleep(milliseconds);
 }
 
 void wxThread::Sleep(unsigned long milliseconds)
 {
     wxMilliSleep(milliseconds);
 }
+
+void *wxThread::CallEntry()
+{
+    wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp);
+    return Entry();
+}
index d72a8fb449c4851921855f9eee88fb353a896b06..8ef745f349cc477eb519590defe91d188974f743 100644 (file)
@@ -28,11 +28,9 @@ namespace
 
 // All thread info objects are stored in a global list so that they are
 // freed when global objects are destroyed and no memory leaks are reported.
 
 // All thread info objects are stored in a global list so that they are
 // freed when global objects are destroyed and no memory leaks are reported.
-//
-// TODO: This could be made more efficient by freeing g_thisThreadInfo when
-//       wxThread terminates.
 wxCriticalSection g_csAllThreadInfos;
 wxCriticalSection g_csAllThreadInfos;
-wxVector< wxSharedPtr<wxThreadSpecificInfo> > g_allThreadInfos;
+typedef wxVector< wxSharedPtr<wxThreadSpecificInfo> > wxAllThreadInfos;
+wxAllThreadInfos g_allThreadInfos;
 
 // Pointer to currenct thread's instance
 wxTLS_TYPE(wxThreadSpecificInfo*) g_thisThreadInfo;
 
 // Pointer to currenct thread's instance
 wxTLS_TYPE(wxThreadSpecificInfo*) g_thisThreadInfo;
@@ -52,6 +50,26 @@ wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
     return *wxTLS_VALUE(g_thisThreadInfo);
 }
 
     return *wxTLS_VALUE(g_thisThreadInfo);
 }
 
+void wxThreadSpecificInfo::ThreadCleanUp()
+{
+    if ( !wxTLS_VALUE(g_thisThreadInfo) )
+        return; // nothing to do, not used by this thread at all
+
+    // find this thread's instance in g_allThreadInfos and destroy it
+    wxCriticalSectionLocker lock(g_csAllThreadInfos);
+    for ( wxAllThreadInfos::iterator i = g_allThreadInfos.begin();
+          i != g_allThreadInfos.end();
+          ++i )
+    {
+        if ( i->get() == wxTLS_VALUE(g_thisThreadInfo) )
+        {
+            g_allThreadInfos.erase(i);
+            wxTLS_VALUE(g_thisThreadInfo) = NULL;
+            break;
+        }
+    }
+}
+
 #else // !wxUSE_THREADS
 
 wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
 #else // !wxUSE_THREADS
 
 wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
index 834d9157d344494947ae14d7f7a7179187bfe2ee..830c0eb1d21fa8667f2f1dc1ec5fa70df2f0daae 100644 (file)
@@ -125,7 +125,7 @@ void wxThreadPrivate::SprocStart(void *ptr)
 
   thr->p_internal->thread_id = getpid();
   thr->p_internal->exit_status = 0;
 
   thr->p_internal->thread_id = getpid();
   thr->p_internal->exit_status = 0;
-  status = thr->Entry();
+  status = thr->CallEntry();
   thr->Exit(status);
 }
 
   thr->Exit(status);
 }
 
index 257c13f4aa3f80259e3eaf56a6f45058044013ed..88e696ab34434165a9fb68efdb5b8800413b1a5a 100644 (file)
@@ -571,7 +571,7 @@ THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread)
             return THREAD_ERROR_EXIT;
         }
 
             return THREAD_ERROR_EXIT;
         }
 
-        rc = wxPtrToUInt(thread->Entry());
+        rc = wxPtrToUInt(thread->CallEntry());
     }
     wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
 
     }
     wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
 
index 94bff21e7c633faa8b618cf4d986b419ed3475d1..f3277d53326fcff281be6dc599841d82e36156fe 100644 (file)
@@ -418,7 +418,7 @@ void wxThreadInternal::OS2ThreadStart( void * pParam )
         unsigned long ulHab;
         if (traits)
             traits->InitializeGui(ulHab);
         unsigned long ulHab;
         if (traits)
             traits->InitializeGui(ulHab);
-        dwRet = (DWORD)pThread->Entry();
+        dwRet = (DWORD)pThread->CallEntry();
         if (traits)
             traits->TerminateGui(ulHab);
 
         if (traits)
             traits->TerminateGui(ulHab);
 
index f4f3d5bd3d6586f221558cfbb5c89bc745e14d8d..dcb7bd778a48dc0a503bc8d764fceb91a38a43e8 100644 (file)
@@ -623,7 +623,7 @@ OSStatus wxThreadInternal::MacThreadStart(void *parameter)
 
     if ( !dontRunAtAll )
     {
 
     if ( !dontRunAtAll )
     {
-        pthread->m_exitcode = thread->Entry();
+        pthread->m_exitcode = thread->CallEntry();
 
         {
             wxCriticalSectionLocker lock(thread->m_critsect);
 
         {
             wxCriticalSectionLocker lock(thread->m_critsect);
index 38897f3b2824f929f8722d8c7d79c0f26a2922e6..4efe5d56f1245aaad4590b101798353ce7ae0f1a 100644 (file)
@@ -864,7 +864,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
 
         wxTRY
         {
 
         wxTRY
         {
-            pthread->m_exitcode = thread->Entry();
+            pthread->m_exitcode = thread->CallEntry();
 
             wxLogTrace(TRACE_THREADS,
                        wxT("Thread %p Entry() returned %lu."),
 
             wxLogTrace(TRACE_THREADS,
                        wxT("Thread %p Entry() returned %lu."),