mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #20841 from alalek:core_keep_TlsAbstraction_singleton_3.4
This commit is contained in:
commit
17bd9a1fa1
@ -53,6 +53,18 @@
|
|||||||
#include <opencv2/core/utils/tls.hpp>
|
#include <opencv2/core/utils/tls.hpp>
|
||||||
#include <opencv2/core/utils/instrumentation.hpp>
|
#include <opencv2/core/utils/instrumentation.hpp>
|
||||||
|
|
||||||
|
#ifndef OPENCV_WITH_THREAD_SANITIZER
|
||||||
|
#if defined(__clang__) && defined(__has_feature)
|
||||||
|
#if __has_feature(thread_sanitizer)
|
||||||
|
#define OPENCV_WITH_THREAD_SANITIZER 1
|
||||||
|
#include <atomic> // assume C++11
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef OPENCV_WITH_THREAD_SANITIZER
|
||||||
|
#define OPENCV_WITH_THREAD_SANITIZER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
|
|
||||||
static void _initSystem()
|
static void _initSystem()
|
||||||
@ -1426,74 +1438,75 @@ namespace details {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class DisposedSingletonMark
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static bool mark;
|
|
||||||
protected:
|
|
||||||
DisposedSingletonMark() {}
|
|
||||||
~DisposedSingletonMark()
|
|
||||||
{
|
|
||||||
mark = true;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
static bool isDisposed() { return mark; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// TLS platform abstraction layer
|
// TLS platform abstraction layer
|
||||||
class TlsAbstraction : public DisposedSingletonMark<TlsAbstraction>
|
class TlsAbstraction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TlsAbstraction();
|
TlsAbstraction();
|
||||||
~TlsAbstraction();
|
~TlsAbstraction()
|
||||||
void* getData() const
|
|
||||||
{
|
{
|
||||||
if (isDisposed()) // guard: static initialization order fiasco
|
// TlsAbstraction singleton should not be released
|
||||||
return NULL;
|
// There is no reliable way to avoid problems caused by static initialization order fiasco
|
||||||
return getData_();
|
// NB: Do NOT use logging here
|
||||||
}
|
fprintf(stderr, "OpenCV FATAL: TlsAbstraction::~TlsAbstraction() call is not expected\n");
|
||||||
void setData(void *pData)
|
fflush(stderr);
|
||||||
{
|
|
||||||
if (isDisposed()) // guard: static initialization order fiasco
|
|
||||||
return;
|
|
||||||
return setData_(pData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* getData() const;
|
||||||
|
void setData(void *pData);
|
||||||
|
|
||||||
|
void releaseSystemResources();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* getData_() const;
|
|
||||||
void setData_(void *pData);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef WINRT
|
#ifndef WINRT
|
||||||
DWORD tlsKey;
|
DWORD tlsKey;
|
||||||
|
bool disposed;
|
||||||
#endif
|
#endif
|
||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
pthread_key_t tlsKey;
|
pthread_key_t tlsKey;
|
||||||
|
#if OPENCV_WITH_THREAD_SANITIZER
|
||||||
|
std::atomic<bool> disposed;
|
||||||
|
#else
|
||||||
|
bool disposed;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> bool DisposedSingletonMark<TlsAbstraction>::mark = false;
|
class TlsAbstractionReleaseGuard
|
||||||
|
|
||||||
static TlsAbstraction& getTlsAbstraction_()
|
|
||||||
{
|
{
|
||||||
static TlsAbstraction g_tls; // disposed in atexit() handlers (required for unregistering our callbacks)
|
TlsAbstraction& tls_;
|
||||||
return g_tls;
|
public:
|
||||||
}
|
TlsAbstractionReleaseGuard(TlsAbstraction& tls) : tls_(tls)
|
||||||
|
{
|
||||||
|
/* nothing */
|
||||||
|
}
|
||||||
|
~TlsAbstractionReleaseGuard()
|
||||||
|
{
|
||||||
|
tls_.releaseSystemResources();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO use reference
|
||||||
static TlsAbstraction* getTlsAbstraction()
|
static TlsAbstraction* getTlsAbstraction()
|
||||||
{
|
{
|
||||||
#ifdef CV_CXX11
|
#ifdef CV_CXX11
|
||||||
static TlsAbstraction* instance = &getTlsAbstraction_();
|
static TlsAbstraction *g_tls = new TlsAbstraction(); // memory leak is intended here to avoid disposing of TLS container
|
||||||
|
static TlsAbstractionReleaseGuard g_tlsReleaseGuard(*g_tls);
|
||||||
#else
|
#else
|
||||||
static TlsAbstraction* volatile instance = NULL;
|
static TlsAbstraction* volatile g_tls = NULL;
|
||||||
if (instance == NULL)
|
if (g_tls == NULL)
|
||||||
{
|
{
|
||||||
cv::AutoLock lock(cv::getInitializationMutex());
|
cv::AutoLock lock(cv::getInitializationMutex());
|
||||||
if (instance == NULL)
|
if (g_tls == NULL)
|
||||||
instance = &getTlsAbstraction_();
|
{
|
||||||
|
g_tls = new TlsAbstraction();
|
||||||
|
static TlsAbstractionReleaseGuard g_tlsReleaseGuard(*g_tls);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return DisposedSingletonMark<TlsAbstraction>::isDisposed() ? NULL : instance;
|
return g_tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1501,12 +1514,15 @@ static TlsAbstraction* getTlsAbstraction()
|
|||||||
#ifdef WINRT
|
#ifdef WINRT
|
||||||
static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
|
static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
|
||||||
TlsAbstraction::TlsAbstraction() {}
|
TlsAbstraction::TlsAbstraction() {}
|
||||||
TlsAbstraction::~TlsAbstraction() {}
|
void TlsAbstraction::releaseSystemResources()
|
||||||
void* TlsAbstraction::getData_() const
|
{
|
||||||
|
cv::__termination = true; // DllMain is missing in static builds
|
||||||
|
}
|
||||||
|
void* TlsAbstraction::getData() const
|
||||||
{
|
{
|
||||||
return tlsData;
|
return tlsData;
|
||||||
}
|
}
|
||||||
void TlsAbstraction::setData_(void *pData)
|
void TlsAbstraction::setData(void *pData)
|
||||||
{
|
{
|
||||||
tlsData = pData;
|
tlsData = pData;
|
||||||
}
|
}
|
||||||
@ -1515,6 +1531,7 @@ void TlsAbstraction::setData_(void *pData)
|
|||||||
static void NTAPI opencv_fls_destructor(void* pData);
|
static void NTAPI opencv_fls_destructor(void* pData);
|
||||||
#endif // CV_USE_FLS
|
#endif // CV_USE_FLS
|
||||||
TlsAbstraction::TlsAbstraction()
|
TlsAbstraction::TlsAbstraction()
|
||||||
|
: disposed(false)
|
||||||
{
|
{
|
||||||
#ifndef CV_USE_FLS
|
#ifndef CV_USE_FLS
|
||||||
tlsKey = TlsAlloc();
|
tlsKey = TlsAlloc();
|
||||||
@ -1523,8 +1540,10 @@ TlsAbstraction::TlsAbstraction()
|
|||||||
#endif // CV_USE_FLS
|
#endif // CV_USE_FLS
|
||||||
CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
|
CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
|
||||||
}
|
}
|
||||||
TlsAbstraction::~TlsAbstraction()
|
void TlsAbstraction::releaseSystemResources()
|
||||||
{
|
{
|
||||||
|
cv::__termination = true; // DllMain is missing in static builds
|
||||||
|
disposed = true;
|
||||||
#ifndef CV_USE_FLS
|
#ifndef CV_USE_FLS
|
||||||
TlsFree(tlsKey);
|
TlsFree(tlsKey);
|
||||||
#else // CV_USE_FLS
|
#else // CV_USE_FLS
|
||||||
@ -1532,16 +1551,20 @@ TlsAbstraction::~TlsAbstraction()
|
|||||||
#endif // CV_USE_FLS
|
#endif // CV_USE_FLS
|
||||||
tlsKey = TLS_OUT_OF_INDEXES;
|
tlsKey = TLS_OUT_OF_INDEXES;
|
||||||
}
|
}
|
||||||
void* TlsAbstraction::getData_() const
|
void* TlsAbstraction::getData() const
|
||||||
{
|
{
|
||||||
|
if (disposed)
|
||||||
|
return NULL;
|
||||||
#ifndef CV_USE_FLS
|
#ifndef CV_USE_FLS
|
||||||
return TlsGetValue(tlsKey);
|
return TlsGetValue(tlsKey);
|
||||||
#else // CV_USE_FLS
|
#else // CV_USE_FLS
|
||||||
return FlsGetValue(tlsKey);
|
return FlsGetValue(tlsKey);
|
||||||
#endif // CV_USE_FLS
|
#endif // CV_USE_FLS
|
||||||
}
|
}
|
||||||
void TlsAbstraction::setData_(void *pData)
|
void TlsAbstraction::setData(void *pData)
|
||||||
{
|
{
|
||||||
|
if (disposed)
|
||||||
|
return; // no-op
|
||||||
#ifndef CV_USE_FLS
|
#ifndef CV_USE_FLS
|
||||||
CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
|
CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
|
||||||
#else // CV_USE_FLS
|
#else // CV_USE_FLS
|
||||||
@ -1552,11 +1575,14 @@ void TlsAbstraction::setData_(void *pData)
|
|||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
static void opencv_tls_destructor(void* pData);
|
static void opencv_tls_destructor(void* pData);
|
||||||
TlsAbstraction::TlsAbstraction()
|
TlsAbstraction::TlsAbstraction()
|
||||||
|
: disposed(false)
|
||||||
{
|
{
|
||||||
CV_Assert(pthread_key_create(&tlsKey, opencv_tls_destructor) == 0);
|
CV_Assert(pthread_key_create(&tlsKey, opencv_tls_destructor) == 0);
|
||||||
}
|
}
|
||||||
TlsAbstraction::~TlsAbstraction()
|
void TlsAbstraction::releaseSystemResources()
|
||||||
{
|
{
|
||||||
|
cv::__termination = true; // DllMain is missing in static builds
|
||||||
|
disposed = true;
|
||||||
if (pthread_key_delete(tlsKey) != 0)
|
if (pthread_key_delete(tlsKey) != 0)
|
||||||
{
|
{
|
||||||
// Don't use logging here
|
// Don't use logging here
|
||||||
@ -1564,12 +1590,16 @@ TlsAbstraction::~TlsAbstraction()
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void* TlsAbstraction::getData_() const
|
void* TlsAbstraction::getData() const
|
||||||
{
|
{
|
||||||
|
if (disposed)
|
||||||
|
return NULL;
|
||||||
return pthread_getspecific(tlsKey);
|
return pthread_getspecific(tlsKey);
|
||||||
}
|
}
|
||||||
void TlsAbstraction::setData_(void *pData)
|
void TlsAbstraction::setData(void *pData)
|
||||||
{
|
{
|
||||||
|
if (disposed)
|
||||||
|
return; // no-op
|
||||||
CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
|
CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1597,6 +1627,7 @@ public:
|
|||||||
TlsStorage() :
|
TlsStorage() :
|
||||||
tlsSlotsSize(0)
|
tlsSlotsSize(0)
|
||||||
{
|
{
|
||||||
|
(void)getTlsAbstraction(); // ensure singeton initialization (for correct order of atexit calls)
|
||||||
tlsSlots.reserve(32);
|
tlsSlots.reserve(32);
|
||||||
threads.reserve(32);
|
threads.reserve(32);
|
||||||
g_isTlsStorageInitialized = true;
|
g_isTlsStorageInitialized = true;
|
||||||
@ -1834,11 +1865,11 @@ static void WINAPI opencv_fls_destructor(void* pData)
|
|||||||
#endif // CV_USE_FLS
|
#endif // CV_USE_FLS
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
static TlsAbstraction* const g_force_initialization_of_TlsAbstraction
|
static TlsStorage* const g_force_initialization_of_TlsStorage
|
||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
#endif
|
#endif
|
||||||
= getTlsAbstraction();
|
= &getTlsStorage();
|
||||||
|
|
||||||
} // namespace details
|
} // namespace details
|
||||||
using namespace details;
|
using namespace details;
|
||||||
|
Loading…
Reference in New Issue
Block a user