When not using compiler TLS support (which is the default now), TLS variable itself needs to be initialized and user-defined code in the global objects ctor could be called before this happened, resulting in using uninitialized CRITICAL_SECTION under Windows and a crash. Fix this by wrapping global wxThreadSpecificInfo itself in an accessor function ensuring that it is always initialized before use. Notice that this required adding wxTLS_TYPE_REF() as wxTLS_TYPE() itself can't be used for the function return value (__thread or similar can only be used on the variables). Closes #16009. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75949 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
104 lines
2.8 KiB
C++
104 lines
2.8 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/threadinfo.cpp
|
|
// Purpose: declaration of wxThreadSpecificInfo: thread-specific information
|
|
// Author: Vaclav Slavik
|
|
// Created: 2013-09-14
|
|
// Copyright: (c) 2013 Vaclav Slavik <vslavik@fastmail.fm>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#if defined(__BORLANDC__)
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include "wx/private/threadinfo.h"
|
|
|
|
#if wxUSE_THREADS
|
|
|
|
#include "wx/tls.h"
|
|
#include "wx/thread.h"
|
|
#include "wx/sharedptr.h"
|
|
#include "wx/vector.h"
|
|
|
|
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.
|
|
|
|
// Notice that we must be using accessor functions instead of simple global
|
|
// variables here as this code could be executed during global initialization
|
|
// time, i.e. before any globals in this module were initialzied.
|
|
inline wxCriticalSection& GetAllThreadInfosCS()
|
|
{
|
|
static wxCriticalSection s_csAllThreadInfos;
|
|
|
|
return s_csAllThreadInfos;
|
|
}
|
|
|
|
typedef wxVector< wxSharedPtr<wxThreadSpecificInfo> > wxAllThreadInfos;
|
|
inline wxAllThreadInfos& GetAllThreadInfos()
|
|
{
|
|
static wxAllThreadInfos s_allThreadInfos;
|
|
|
|
return s_allThreadInfos;
|
|
}
|
|
|
|
// Pointer to the current thread's instance
|
|
inline wxTLS_TYPE_REF(wxThreadSpecificInfo*) GetThisThreadInfo()
|
|
{
|
|
static wxTLS_TYPE(wxThreadSpecificInfo*) s_thisThreadInfo;
|
|
|
|
return s_thisThreadInfo;
|
|
}
|
|
|
|
#define wxTHIS_THREAD_INFO wxTLS_VALUE(GetThisThreadInfo())
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
|
|
{
|
|
if ( !wxTHIS_THREAD_INFO )
|
|
{
|
|
wxTHIS_THREAD_INFO = new wxThreadSpecificInfo;
|
|
wxCriticalSectionLocker lock(GetAllThreadInfosCS());
|
|
GetAllThreadInfos().push_back(
|
|
wxSharedPtr<wxThreadSpecificInfo>(wxTHIS_THREAD_INFO));
|
|
}
|
|
return *wxTHIS_THREAD_INFO;
|
|
}
|
|
|
|
void wxThreadSpecificInfo::ThreadCleanUp()
|
|
{
|
|
if ( !wxTHIS_THREAD_INFO )
|
|
return; // nothing to do, not used by this thread at all
|
|
|
|
// find this thread's instance in GetAllThreadInfos() and destroy it
|
|
wxCriticalSectionLocker lock(GetAllThreadInfosCS());
|
|
for ( wxAllThreadInfos::iterator i = GetAllThreadInfos().begin();
|
|
i != GetAllThreadInfos().end();
|
|
++i )
|
|
{
|
|
if ( i->get() == wxTHIS_THREAD_INFO )
|
|
{
|
|
GetAllThreadInfos().erase(i);
|
|
wxTHIS_THREAD_INFO = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#else // !wxUSE_THREADS
|
|
|
|
wxThreadSpecificInfo& wxThreadSpecificInfo::Get()
|
|
{
|
|
static wxThreadSpecificInfo s_instance;
|
|
return s_instance;
|
|
}
|
|
|
|
#endif // wxUSE_THREADS/wxUSE_THREADS
|