summaryrefslogtreecommitdiff
path: root/misc.h
diff options
context:
space:
mode:
authorweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2003-07-29 01:18:33 +0000
committerweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2003-07-29 01:18:33 +0000
commit483c74aaab7c20d82a48621f1dd8b300292d3404 (patch)
tree7a78ed3becd2c14f449d1cc66a58edd414256d94 /misc.h
parenta01d216aab60849e4581efd41820f18562085687 (diff)
downloadcryptopp-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.h42
1 files changed, 35 insertions, 7 deletions
diff --git a/misc.h b/misc.h
index 790e459..659ba2a 100644
--- a/misc.h
+++ b/misc.h
@@ -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 ***************