From b3af8bd5f91c5f2f3056c7d955bebb0ae7d2ddfb Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 2 Jun 2015 10:24:38 +0100 Subject: [PATCH] implement DCLP using c++11 (http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/) ref #2838 --- include/mapnik/utils.hpp | 61 +++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp index a306f1c6c..be426e520 100644 --- a/include/mapnik/utils.hpp +++ b/include/mapnik/utils.hpp @@ -29,7 +29,7 @@ #include // std::runtime_error #include // std::atexit #include // operator new - +#include #ifdef MAPNIK_THREADSAFE #include #endif @@ -88,43 +88,46 @@ template class CreatePolicy=CreateStatic> class MAPNIK_DECL singleton { #else -template class CreatePolicy=CreateStatic> class singleton -{ + template class CreatePolicy=CreateStatic> class singleton + { #endif - friend class CreatePolicy; - static T* pInstance_; - static bool destroyed_; - singleton(const singleton &rhs); - singleton& operator=(const singleton&); + friend class CreatePolicy; + static std::atomic pInstance_; + static bool destroyed_; + singleton(const singleton &rhs); + singleton& operator=(const singleton&); - static void onDeadReference() - { - throw std::runtime_error("dead reference!"); - } + static void onDeadReference() + { + throw std::runtime_error("dead reference!"); + } - static void DestroySingleton() - { - CreatePolicy::destroy(pInstance_); - pInstance_ = 0; - destroyed_ = true; - } + static void DestroySingleton() + { + CreatePolicy::destroy(pInstance_); + pInstance_ = 0; + destroyed_ = true; + } -protected: + protected: #ifdef MAPNIK_THREADSAFE static std::mutex mutex_; #endif singleton() {} + public: static T& instance() { - if (! pInstance_) + T * tmp = pInstance_.load(std::memory_order_acquire); + if (tmp == nullptr) { #ifdef MAPNIK_THREADSAFE std::lock_guard lock(mutex_); #endif - if (! pInstance_) + tmp = pInstance_.load(std::memory_order_relaxed); + if (tmp == nullptr) { if (destroyed_) { @@ -133,16 +136,16 @@ protected: } else { - pInstance_ = CreatePolicy::create(); - + tmp = CreatePolicy::create(); + pInstance_.store(tmp, std::memory_order_release); // register destruction std::atexit(&DestroySingleton); } } } - return *pInstance_; + return *tmp; } -}; + }; #ifdef MAPNIK_THREADSAFE template class CreatePolicy> T* singleton::pInstance_=0; + template class CreatePolicy> std::atomic singleton::pInstance_; template class CreatePolicy> bool singleton::destroyed_=false; @@ -159,8 +162,8 @@ protected: // UTF8 <--> UTF16 conversion routines -MAPNIK_DECL std::string utf16_to_utf8(std::wstring const& wstr); -MAPNIK_DECL std::wstring utf8_to_utf16(std::string const& str); + MAPNIK_DECL std::string utf16_to_utf8(std::wstring const& wstr); + MAPNIK_DECL std::wstring utf8_to_utf16(std::string const& str); #endif // _WINDOWS