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;
#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) {}
};

View File

@ -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

View File

@ -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();
}

View 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.
//
// TODO: This could be made more efficient by freeing g_thisThreadInfo when
// wxThread terminates.
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;
@ -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()

View File

@ -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);
}

View File

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

View File

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

View File

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

View File

@ -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."),