diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index e3fd0e4c4..ef01c2139 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2026,8 +2026,7 @@ class OCL_FftPlanCache public: static OCL_FftPlanCache & getInstance() { - static OCL_FftPlanCache planCache; - return planCache; + CV_SINGLETON_LAZY_INIT_REF(OCL_FftPlanCache, new OCL_FftPlanCache()) } Ptr getFftPlan(int dft_size, int depth) @@ -2291,8 +2290,7 @@ class PlanCache public: static PlanCache & getInstance() { - static PlanCache planCache; - return planCache; + CV_SINGLETON_LAZY_INIT_REF(PlanCache, new PlanCache()) } clAmdFftPlanHandle getPlanHandle(const Size & dft_size, int src_step, int dst_step, bool doubleFP, diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index a0ee4316d..b512485d1 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -205,8 +205,7 @@ public: static MatOp_Initializer* getGlobalMatOpInitializer() { - static MatOp_Initializer initializer; - return &initializer; + CV_SINGLETON_LAZY_INIT(MatOp_Initializer, new MatOp_Initializer()) } static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; } diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 5de7e034f..9b39fe64d 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -222,14 +222,9 @@ public: } }; -static StdMatAllocator *mat_allocator = NULL; MatAllocator* Mat::getStdAllocator() { - if (mat_allocator == NULL) - { - mat_allocator = new StdMatAllocator(); - } - return mat_allocator; + CV_SINGLETON_LAZY_INIT(MatAllocator, new StdMatAllocator()) } void swap( Mat& a, Mat& b ) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 9d25eb073..0378b66c0 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1510,8 +1510,7 @@ class AmdBlasHelper public: static AmdBlasHelper & getInstance() { - static AmdBlasHelper amdBlas; - return amdBlas; + CV_SINGLETON_LAZY_INIT_REF(AmdBlasHelper, new AmdBlasHelper()) } bool isAvailable() const @@ -1533,35 +1532,36 @@ protected: { if (!g_isAmdBlasInitialized) { - AutoLock lock(m); + AutoLock lock(getInitializationMutex()); - if (!g_isAmdBlasInitialized && haveOpenCL()) + if (!g_isAmdBlasInitialized) { - try + if (haveOpenCL()) { - g_isAmdBlasAvailable = clAmdBlasSetup() == clAmdBlasSuccess; + try + { + g_isAmdBlasAvailable = clAmdBlasSetup() == clAmdBlasSuccess; + } + catch (...) + { + g_isAmdBlasAvailable = false; + } } - catch (...) - { + else g_isAmdBlasAvailable = false; - } - } - else - g_isAmdBlasAvailable = false; - g_isAmdBlasInitialized = true; + g_isAmdBlasInitialized = true; + } } } private: - static Mutex m; static bool g_isAmdBlasInitialized; static bool g_isAmdBlasAvailable; }; bool AmdBlasHelper::g_isAmdBlasAvailable = false; bool AmdBlasHelper::g_isAmdBlasInitialized = false; -Mutex AmdBlasHelper::m; bool haveAmdBlas() { @@ -1584,8 +1584,7 @@ class AmdFftHelper public: static AmdFftHelper & getInstance() { - static AmdFftHelper amdFft; - return amdFft; + CV_SINGLETON_LAZY_INIT_REF(AmdFftHelper, new AmdFftHelper()) } bool isAvailable() const @@ -1607,34 +1606,36 @@ protected: { if (!g_isAmdFftInitialized) { - AutoLock lock(m); + AutoLock lock(getInitializationMutex()); - if (!g_isAmdFftInitialized && haveOpenCL()) + if (!g_isAmdFftInitialized) { - try + if (haveOpenCL()) { - cl_uint major, minor, patch; - CV_Assert(clAmdFftInitSetupData(&setupData) == CLFFT_SUCCESS); + try + { + cl_uint major, minor, patch; + CV_Assert(clAmdFftInitSetupData(&setupData) == CLFFT_SUCCESS); - // it throws exception in case AmdFft binaries are not found - CV_Assert(clAmdFftGetVersion(&major, &minor, &patch) == CLFFT_SUCCESS); - g_isAmdFftAvailable = true; + // it throws exception in case AmdFft binaries are not found + CV_Assert(clAmdFftGetVersion(&major, &minor, &patch) == CLFFT_SUCCESS); + g_isAmdFftAvailable = true; + } + catch (const Exception &) + { + g_isAmdFftAvailable = false; + } } - catch (const Exception &) - { + else g_isAmdFftAvailable = false; - } - } - else - g_isAmdFftAvailable = false; - g_isAmdFftInitialized = true; + g_isAmdFftInitialized = true; + } } } private: static clAmdFftSetupData setupData; - static Mutex m; static bool g_isAmdFftInitialized; static bool g_isAmdFftAvailable; }; @@ -1642,7 +1643,6 @@ private: clAmdFftSetupData AmdFftHelper::setupData; bool AmdFftHelper::g_isAmdFftAvailable = false; bool AmdFftHelper::g_isAmdFftInitialized = false; -Mutex AmdFftHelper::m; bool haveAmdFft() { @@ -5237,15 +5237,9 @@ public: MatAllocator* matStdAllocator; }; -// This line should not force OpenCL runtime initialization! (don't put "new OpenCLAllocator()" here) -static MatAllocator *ocl_allocator = NULL; MatAllocator* getOpenCLAllocator() { - if (ocl_allocator == NULL) - { - ocl_allocator = new OpenCLAllocator(); - } - return ocl_allocator; + CV_SINGLETON_LAZY_INIT(MatAllocator, new OpenCLAllocator()) } }} // namespace cv::ocl diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 88b60e471..d8d7e007e 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -295,6 +295,22 @@ TLSData& getCoreTlsData(); extern bool __termination; // skip some cleanups, because process is terminating // (for example, if ExitProcess() was already called) +cv::Mutex& getInitializationMutex(); + +// TODO Memory barriers? +#define CV_SINGLETON_LAZY_INIT_(TYPE, INITIALIZER, RET_VALUE) \ + static TYPE* volatile instance = NULL; \ + if (instance == NULL) \ + { \ + cv::AutoLock lock(cv::getInitializationMutex()); \ + if (instance == NULL) \ + instance = INITIALIZER; \ + } \ + return RET_VALUE; + +#define CV_SINGLETON_LAZY_INIT(TYPE, INITIALIZER) CV_SINGLETON_LAZY_INIT_(TYPE, INITIALIZER, instance) +#define CV_SINGLETON_LAZY_INIT_REF(TYPE, INITIALIZER) CV_SINGLETON_LAZY_INIT_(TYPE, INITIALIZER, *instance) + } #include "opencv2/hal/intrin.hpp" diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 46f41dcca..6a85c40ee 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -43,6 +43,20 @@ #include "precomp.hpp" +namespace cv { + +static Mutex* __initialization_mutex = NULL; +Mutex& getInitializationMutex() +{ + if (__initialization_mutex == NULL) + __initialization_mutex = new Mutex(); + return *__initialization_mutex; +} +// force initialization (single-threaded environment) +Mutex* __initialization_mutex_initializer = &getInitializationMutex(); + +} // namespace cv + #ifdef _MSC_VER # if _MSC_VER >= 1700 # pragma warning(disable:4447) // Disable warning 'main' signature found without threading model @@ -1108,8 +1122,7 @@ public: // For more information: http://www.parashift.com/c++-faq/static-init-order-on-first-use.html static TLSContainerStorage& getTLSContainerStorage() { - static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage(); - return *tlsContainerStorage; + CV_SINGLETON_LAZY_INIT_REF(TLSContainerStorage, new TLSContainerStorage()) } TLSDataContainer::TLSDataContainer() @@ -1153,20 +1166,16 @@ TLSStorage::~TLSStorage() } - TLSData& getCoreTlsData() { - static TLSData *value = new TLSData(); - return *value; + CV_SINGLETON_LAZY_INIT_REF(TLSData, new TLSData()) } - #ifdef CV_COLLECT_IMPL_DATA ImplCollector& getImplData() { - static ImplCollector *value = new ImplCollector(); - return *value; + CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector()) } void setImpl(int flags)