diff options
author | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2003-07-29 01:18:33 +0000 |
---|---|---|
committer | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2003-07-29 01:18:33 +0000 |
commit | 483c74aaab7c20d82a48621f1dd8b300292d3404 (patch) | |
tree | 7a78ed3becd2c14f449d1cc66a58edd414256d94 /misc.h | |
parent | a01d216aab60849e4581efd41820f18562085687 (diff) | |
download | cryptopp-483c74aaab7c20d82a48621f1dd8b300292d3404.tar.gz |
fix potential threading problem with initialization of static objects
git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@118 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'misc.h')
-rw-r--r-- | misc.h | 42 |
1 files changed, 35 insertions, 7 deletions
@@ -209,29 +209,57 @@ inline CipherDir GetCipherDir(const T &obj) return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; } +template <class T> +struct NewObject +{ + T* operator()() const {return new T;} +}; + // This function safely initializes a static object in a multithreaded environment without using locks. // It may leak memory when two threads try to initialize the static object at the same time // but this should be acceptable since each static object is only initialized once per session. -template <class T, class F> -T & StaticObject(F NewT, T *dummy=NULL) +template <class T, class F = NewObject<T>, int instance=0> +class Singleton { - static member_ptr<T> s_pObject; +public: + Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} + + // VC60 workaround: use "..." to prevent this function from being inlined + const T & Ref(...) const; + +private: + F m_objectFactory; +}; + +template <class T, class F, int instance> +const T & Singleton<T, F, instance>::Ref(...) const +{ + static simple_ptr<T> s_pObject; static char s_objectState = 0; +retry: switch (s_objectState) { case 0: s_objectState = 1; - s_pObject.reset(NewT()); + try + { + s_pObject.m_p = m_objectFactory(); + } + catch(...) + { + s_objectState = 0; + throw; + } s_objectState = 2; break; case 1: - while (s_objectState == 1) {} + goto retry; default: break; } - return *s_pObject; -}; + return *s_pObject.m_p; +} // ************** rotate functions *************** |