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
This commit is contained in:
Václav Slavík
2013-09-18 16:03:25 +00:00
parent d2740de55e
commit 5278469615
9 changed files with 44 additions and 9 deletions

View File

@@ -52,6 +52,13 @@ public:
wxLocaleUntranslatedStrings untranslatedStrings; wxLocaleUntranslatedStrings untranslatedStrings;
#endif #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: private:
wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {} wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {}
}; };

View File

@@ -614,6 +614,8 @@ protected:
// of this thread. // of this thread.
virtual void *Entry() = 0; 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 // Callbacks which may be overridden by the derived class to perform some
// specific actions when the thread is deleted or killed. By default they // specific actions when the thread is deleted or killed. By default they

View 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) void wxThread::Sleep(unsigned long milliseconds)
{ {
wxMilliSleep(milliseconds); wxMilliSleep(milliseconds);
} }
void *wxThread::CallEntry()
{
wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp);
return Entry();
}

View File

@@ -28,11 +28,9 @@ namespace
// All thread info objects are stored in a global list so that they are // 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. // 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 // Pointer to currenct thread's instance
wxTLS_TYPE(wxThreadSpecificInfo*) g_thisThreadInfo; 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 #else // !wxUSE_THREADS
wxThreadSpecificInfo& wxThreadSpecificInfo::Get() wxThreadSpecificInfo& wxThreadSpecificInfo::Get()

View File

@@ -125,7 +125,7 @@ void wxThreadPrivate::SprocStart(void *ptr)
thr->p_internal->thread_id = getpid(); thr->p_internal->thread_id = getpid();
thr->p_internal->exit_status = 0; thr->p_internal->exit_status = 0;
status = thr->Entry(); status = thr->CallEntry();
thr->Exit(status); thr->Exit(status);
} }

View 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(); )

View File

@@ -418,7 +418,7 @@ void wxThreadInternal::OS2ThreadStart( void * pParam )
unsigned long ulHab; unsigned long ulHab;
if (traits) if (traits)
traits->InitializeGui(ulHab); traits->InitializeGui(ulHab);
dwRet = (DWORD)pThread->Entry(); dwRet = (DWORD)pThread->CallEntry();
if (traits) if (traits)
traits->TerminateGui(ulHab); traits->TerminateGui(ulHab);

View 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);

View 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, wxLogTrace(TRACE_THREADS,
wxT("Thread %p Entry() returned %lu."), wxT("Thread %p Entry() returned %lu."),