diff --git a/cpp/src/phonenumbers/base/memory/singleton.h b/cpp/src/phonenumbers/base/memory/singleton.h index 43c5a1aa6..38b4bfc4e 100644 --- a/cpp/src/phonenumbers/base/memory/singleton.h +++ b/cpp/src/phonenumbers/base/memory/singleton.h @@ -50,7 +50,8 @@ template boost::once_flag Singleton::flag = BOOST_ONCE_INIT; #else // !I18N_PHONENUMBERS_USE_BOOST -#include "phonenumbers/base/thread_safety_check.h" +#include "phonenumbers/base/logging.h" +#include "phonenumbers/base/thread_checker.h" namespace i18n { namespace phonenumbers { @@ -60,6 +61,8 @@ namespace phonenumbers { template class Singleton { public: + Singleton() : thread_checker_() {} + virtual ~Singleton() {} static T* GetInstance() { @@ -67,8 +70,12 @@ class Singleton { if (!instance) { instance = new T(); } + DCHECK(instance->thread_checker_.CalledOnValidThread()); return instance; } + + private: + const ThreadChecker thread_checker_; }; #endif // !I18N_PHONENUMBERS_USE_BOOST diff --git a/cpp/src/phonenumbers/base/synchronization/lock.h b/cpp/src/phonenumbers/base/synchronization/lock.h index c68fefd60..7ef136c20 100644 --- a/cpp/src/phonenumbers/base/synchronization/lock.h +++ b/cpp/src/phonenumbers/base/synchronization/lock.h @@ -30,17 +30,35 @@ typedef boost::mutex::scoped_lock AutoLock; } // namespace i18n #else // I18N_PHONENUMBERS_USE_BOOST -#include "phonenumbers/base/thread_safety_check.h" + +#include "phonenumbers/base/logging.h" +#include "phonenumbers/base/thread_checker.h" namespace i18n { namespace phonenumbers { // Dummy lock implementation. If you care about thread-safety, please compile // with -DI18N_PHONENUMBERS_USE_BOOST. -struct Lock {}; +class Lock { + public: + Lock() : thread_checker_() {} + + void Acquire() const { + DCHECK(thread_checker_.CalledOnValidThread()); + } + + // No need for Release() since Acquire() is a no-op and Release() is not used + // in the codebase. + + private: + const ThreadChecker thread_checker_; +}; -struct AutoLock { - AutoLock(Lock) {} +class AutoLock { + public: + AutoLock(Lock& lock) { + lock.Acquire(); + } }; } // namespace phonenumbers diff --git a/cpp/src/phonenumbers/base/thread_safety_check.h b/cpp/src/phonenumbers/base/thread_checker.h similarity index 66% rename from cpp/src/phonenumbers/base/thread_safety_check.h rename to cpp/src/phonenumbers/base/thread_checker.h index b11bdf576..38ef54c26 100644 --- a/cpp/src/phonenumbers/base/thread_safety_check.h +++ b/cpp/src/phonenumbers/base/thread_checker.h @@ -28,4 +28,41 @@ #endif +#if !defined(NDEBUG) && !defined(I18N_PHONENUMBERS_USE_BOOST) && \ + (defined(__linux__) || defined(__apple__)) + +#include + +namespace i18n { +namespace phonenumbers { + +class ThreadChecker { + public: + ThreadChecker() : thread_id_(pthread_self()) {} + + bool CalledOnValidThread() const { + return thread_id_ == pthread_self(); + } + + private: + const pthread_t thread_id_; +}; + +#else + +namespace i18n { +namespace phonenumbers { + +class ThreadChecker { + public: + bool CalledOnValidThread() const { + return true; + } +}; + +#endif + +} // namespace phonenumbers +} // namespace i18n + #endif // I18N_PHONENUMBERS_BASE_THREAD_SAFETY_CHECK_H_