From 050a520ddf9a34b93a3b41704fa2450d7450783f Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 24 Feb 2010 17:19:25 +0000 Subject: Adds threading support (by Miklos Fazekas, Vlad Losev, and Chandler Carruth); adds wide InitGoogleTest to gtest.def (by Vlad Losev); updates the version number (by Zhanyong Wan); updates the release notes for 1.5.0 (by Vlad Losev); removes scons scripts from the distribution (by Zhanyong Wan); adds the cmake build script to the distribution (by Zhanyong Wan); adds fused source files to the distribution (by Vlad Losev and Chandler Carruth). git-svn-id: http://googletest.googlecode.com/svn/trunk@376 861a406c-534a-0410-8894-cb66d6ee9925 --- src/gtest-internal-inl.h | 5 ++- src/gtest-port.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gtest.cc | 2 +- 3 files changed, 93 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h index 596dc55..4142e7a 100644 --- a/src/gtest-internal-inl.h +++ b/src/gtest-internal-inl.h @@ -60,7 +60,7 @@ #include // For DWORD. #endif // GTEST_OS_WINDOWS -#include +#include // NOLINT #include namespace testing { @@ -1228,6 +1228,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) { // TestResult contains some private methods that should be hidden from // Google Test user but are required for testing. This class allow our tests // to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. class TestResultAccessor { public: static void RecordProperty(TestResult* test_result, diff --git a/src/gtest-port.cc b/src/gtest-port.cc index b9504f5..5994fd5 100644 --- a/src/gtest-port.cc +++ b/src/gtest-port.cc @@ -75,6 +75,94 @@ const int kStdOutFileno = STDOUT_FILENO; const int kStdErrFileno = STDERR_FILENO; #endif // _MSC_VER +#if GTEST_HAS_PTHREAD + +// ThreadStartSemaphore allows the controller thread to pause execution of +// newly created test threads until signalled. Instances of this class must +// be created and destroyed in the controller thread. +ThreadStartSemaphore::ThreadStartSemaphore() : signalled_(false) { + int err = pthread_mutex_init(&mutex_, NULL); + GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err; + err = pthread_cond_init(&cond_, NULL); + GTEST_CHECK_(err == 0) << "pthread_cond_init failed with error " << err; + pthread_mutex_lock(&mutex_); +} + +ThreadStartSemaphore::~ThreadStartSemaphore() { + // Every ThreadStartSemaphore object must be signalled. It locks + // internal mutex upon creation and Signal unlocks it. + GTEST_CHECK_(signalled_); + + int err = pthread_mutex_destroy(&mutex_); + GTEST_CHECK_(err == 0) + << "pthread_mutex_destroy failed with error " << err; + err = pthread_cond_destroy(&cond_); + GTEST_CHECK_(err == 0) + << "pthread_cond_destroy failed with error " << err; +} + +// Signals to all test threads to start. Must be called from the +// controlling thread. +void ThreadStartSemaphore::Signal() { + signalled_ = true; + int err = pthread_cond_signal(&cond_); + GTEST_CHECK_(err == 0) + << "pthread_cond_signal failed with error " << err; + err = pthread_mutex_unlock(&mutex_); + GTEST_CHECK_(err == 0) + << "pthread_mutex_unlock failed with error " << err; +} + +// Blocks until the controlling thread signals. Should be called from a +// test thread. +void ThreadStartSemaphore::Wait() { + int err = pthread_mutex_lock(&mutex_); + GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err; + + while (!signalled_) { + err = pthread_cond_wait(&cond_, &mutex_); + GTEST_CHECK_(err == 0) + << "pthread_cond_wait failed with error " << err; + } + err = pthread_mutex_unlock(&mutex_); + GTEST_CHECK_(err == 0) + << "pthread_mutex_unlock failed with error " << err; +} + +void MutexBase::Lock() { + const int err = pthread_mutex_lock(&mutex_); + GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err; + owner_ = pthread_self(); +} + +void MutexBase::Unlock() { + // We don't protect writing to owner_ here, as it's the caller's + // responsibility to ensure that the current thread holds the mutex when + // this is called. + owner_ = 0; + const int err = pthread_mutex_unlock(&mutex_); + GTEST_CHECK_(err == 0) << "pthread_mutex_unlock failed with error " << err; +} + +// Does nothing if the current thread holds the mutex. Otherwise, crashes +// with high probability. +void MutexBase::AssertHeld() const { + GTEST_CHECK_(owner_ == pthread_self()) + << "Current thread is not holding mutex." << this; +} + +Mutex::Mutex() { + owner_ = 0; + const int err = pthread_mutex_init(&mutex_, NULL); + GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err; +} + +Mutex::~Mutex() { + const int err = pthread_mutex_destroy(&mutex_); + GTEST_CHECK_(err == 0) << "pthread_mutex_destroy failed with error " << err; +} +#endif // GTEST_HAS_PTHREAD + #if GTEST_OS_MAC // Returns the number of threads running in the process, or 0 to indicate that diff --git a/src/gtest.cc b/src/gtest.cc index fb5bae9..3306f3f 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -342,7 +342,7 @@ void AssertHelper::operator=(const Message& message) const { } // Mutex for linked pointers. -Mutex g_linked_ptr_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); +GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); // Application pathname gotten in InitGoogleTest. String g_executable_path; -- cgit v1.2.1