From 5278469615164a60b22435aae4734e106aba540d Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Wed, 18 Sep 2013 16:03:25 +0000 Subject: [PATCH] Deallocate wxThreadSpecificInfo when wxThread ends. 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 | 7 +++++++ include/wx/thread.h | 2 ++ include/wx/thrimpl.cpp | 8 ++++++++ src/common/threadinfo.cpp | 26 ++++++++++++++++++++++---- src/gtk1/threadsgi.cpp | 2 +- src/msw/thread.cpp | 2 +- src/os2/thread.cpp | 2 +- src/osx/carbon/thread.cpp | 2 +- src/unix/threadpsx.cpp | 2 +- 9 files changed, 44 insertions(+), 9 deletions(-) diff --git a/include/wx/private/threadinfo.h b/include/wx/private/threadinfo.h index 1ff241bda8..27a71674b0 100644 --- a/include/wx/private/threadinfo.h +++ b/include/wx/private/threadinfo.h @@ -52,6 +52,13 @@ public: 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) {} }; diff --git a/include/wx/thread.h b/include/wx/thread.h index 086007f826..6806d82fea 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -614,6 +614,8 @@ protected: // 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 diff --git a/include/wx/thrimpl.cpp b/include/wx/thrimpl.cpp index 737ff85fa1..000b24d589 100644 --- a/include/wx/thrimpl.cpp +++ b/include/wx/thrimpl.cpp @@ -342,8 +342,16 @@ wxSemaError wxSemaphore::Post() // ---------------------------------------------------------------------------- #include "wx/utils.h" +#include "wx/private/threadinfo.h" +#include "wx/scopeguard.h" void wxThread::Sleep(unsigned long milliseconds) { wxMilliSleep(milliseconds); } + +void *wxThread::CallEntry() +{ + wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp); + return Entry(); +} diff --git a/src/common/threadinfo.cpp b/src/common/threadinfo.cpp index d72a8fb449..8ef745f349 100644 --- a/src/common/threadinfo.cpp +++ b/src/common/threadinfo.cpp @@ -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. -// -// TODO: This could be made more efficient by freeing g_thisThreadInfo when -// wxThread terminates. wxCriticalSection g_csAllThreadInfos; -wxVector< wxSharedPtr > g_allThreadInfos; +typedef wxVector< wxSharedPtr > wxAllThreadInfos; +wxAllThreadInfos g_allThreadInfos; // Pointer to currenct thread's instance wxTLS_TYPE(wxThreadSpecificInfo*) g_thisThreadInfo; @@ -52,6 +50,26 @@ wxThreadSpecificInfo& wxThreadSpecificInfo::Get() 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() diff --git a/src/gtk1/threadsgi.cpp b/src/gtk1/threadsgi.cpp index 834d9157d3..830c0eb1d2 100644 --- a/src/gtk1/threadsgi.cpp +++ b/src/gtk1/threadsgi.cpp @@ -125,7 +125,7 @@ void wxThreadPrivate::SprocStart(void *ptr) thr->p_internal->thread_id = getpid(); thr->p_internal->exit_status = 0; - status = thr->Entry(); + status = thr->CallEntry(); thr->Exit(status); } diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 257c13f4aa..88e696ab34 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -571,7 +571,7 @@ THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread) return THREAD_ERROR_EXIT; } - rc = wxPtrToUInt(thread->Entry()); + rc = wxPtrToUInt(thread->CallEntry()); } wxCATCH_ALL( wxTheApp->OnUnhandledException(); ) diff --git a/src/os2/thread.cpp b/src/os2/thread.cpp index 94bff21e7c..f3277d5332 100644 --- a/src/os2/thread.cpp +++ b/src/os2/thread.cpp @@ -418,7 +418,7 @@ void wxThreadInternal::OS2ThreadStart( void * pParam ) unsigned long ulHab; if (traits) traits->InitializeGui(ulHab); - dwRet = (DWORD)pThread->Entry(); + dwRet = (DWORD)pThread->CallEntry(); if (traits) traits->TerminateGui(ulHab); diff --git a/src/osx/carbon/thread.cpp b/src/osx/carbon/thread.cpp index f4f3d5bd3d..dcb7bd778a 100644 --- a/src/osx/carbon/thread.cpp +++ b/src/osx/carbon/thread.cpp @@ -623,7 +623,7 @@ OSStatus wxThreadInternal::MacThreadStart(void *parameter) if ( !dontRunAtAll ) { - pthread->m_exitcode = thread->Entry(); + pthread->m_exitcode = thread->CallEntry(); { wxCriticalSectionLocker lock(thread->m_critsect); diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 38897f3b28..4efe5d56f1 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -864,7 +864,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) wxTRY { - pthread->m_exitcode = thread->Entry(); + pthread->m_exitcode = thread->CallEntry(); wxLogTrace(TRACE_THREADS, wxT("Thread %p Entry() returned %lu."), -- 2.45.2