diff options
author | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2010-06-18 07:06:59 +0000 |
---|---|---|
committer | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2010-06-18 07:06:59 +0000 |
commit | e562437c88d18d206d079aa0ed07f5be57203a4a (patch) | |
tree | 2c3909fc3181e50ef34814d62769b02277bc13a5 /misc.h | |
parent | 70a991f0023a3bd23bfd6ffd0b665f1dbed701bf (diff) | |
download | cryptopp-e562437c88d18d206d079aa0ed07f5be57203a4a.tar.gz |
fix possible race condition in Singleton::Ref()
tolerate double destruction of Singleton and g_nullNameValuePairs
fix #include of standard headers
git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@488 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'misc.h')
-rw-r--r-- | misc.h | 45 |
1 files changed, 18 insertions, 27 deletions
@@ -6,7 +6,6 @@ #include <string.h> // for memcpy and memmove #ifdef _MSC_VER - #include <stdlib.h> #if _MSC_VER >= 1400 // VC2005 workaround: disable declarations that conflict with winnt.h #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1 @@ -101,9 +100,9 @@ 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. +/*! This function safely initializes a static object in a multithreaded environment without using locks (for portability). + Note that if two threads call Ref() at the same time, they may get back different references, and one object + may end up being memory leaked. This is by design. */ template <class T, class F = NewObject<T>, int instance=0> class Singleton @@ -121,31 +120,23 @@ private: template <class T, class F, int instance> const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const { - static simple_ptr<T> s_pObject; - static volatile char s_objectState = 0; + static volatile simple_ptr<T> s_pObject; + T *p = s_pObject.m_p; -retry: - switch (s_objectState) + if (p) + return *p; + + T *newObject = m_objectFactory(); + p = s_pObject.m_p; + + if (p) { - case 0: - s_objectState = 1; - try - { - s_pObject.m_p = m_objectFactory(); - } - catch(...) - { - s_objectState = 0; - throw; - } - s_objectState = 2; - break; - case 1: - goto retry; - default: - break; + delete newObject; + return *p; } - return *s_pObject.m_p; + + s_pObject.m_p = newObject; + return *newObject; } // ************** misc functions *************** @@ -555,7 +546,7 @@ static std::string StringNarrow(const wchar_t *str, bool throwOnError = true) #pragma warning(disable: 4996) // 'wcstombs': This function or variable may be unsafe. #endif size_t size = wcstombs(NULL, str, 0); - if (size == -1) + if (size == size_t(0)-1) { if (throwOnError) throw InvalidArgument("StringNarrow: wcstombs() call failed"); |