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) {}
};
// 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
// ----------------------------------------------------------------------------
#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();
+}
// 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;
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()
thr->p_internal->thread_id = getpid();
thr->p_internal->exit_status = 0;
- status = thr->Entry();
+ status = thr->CallEntry();
thr->Exit(status);
}
return THREAD_ERROR_EXIT;
}
- rc = wxPtrToUInt(thread->Entry());
+ rc = wxPtrToUInt(thread->CallEntry());
}
wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
unsigned long ulHab;
if (traits)
traits->InitializeGui(ulHab);
- dwRet = (DWORD)pThread->Entry();
+ dwRet = (DWORD)pThread->CallEntry();
if (traits)
traits->TerminateGui(ulHab);
if ( !dontRunAtAll )
{
- pthread->m_exitcode = thread->Entry();
+ pthread->m_exitcode = thread->CallEntry();
{
wxCriticalSectionLocker lock(thread->m_critsect);
wxTRY
{
- pthread->m_exitcode = thread->Entry();
+ pthread->m_exitcode = thread->CallEntry();
wxLogTrace(TRACE_THREADS,
wxT("Thread %p Entry() returned %lu."),