diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h index bdf75e2f..6910c7b7 100644 --- a/include/gtest/internal/gtest-port.h +++ b/include/gtest/internal/gtest-port.h @@ -220,6 +220,7 @@ #include // NOLINT #include // NOLINT #include // NOLINT +#include // NOLINT #include // NOLINT #define GTEST_USES_POSIX_RE 1 @@ -935,28 +936,41 @@ class ThreadLocal { GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + // Allows a controller thread to pause execution of newly created // threads until signalled. Instances of this class must be created // and destroyed in the controller thread. // -// This class is supplied only for testing Google Test's own -// constructs. Do not use it in user tests, either directly or indirectly. +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. class ThreadStartSemaphore { public: - ThreadStartSemaphore(); - ~ThreadStartSemaphore(); + ThreadStartSemaphore() : signalled_(false) {} + // Signals to all threads created with this semaphore to start. Must // be called from the controller thread. - void Signal(); + void Signal() { signalled_ = true; } + // Blocks until the controller thread signals. Must be called from a test // thread. - void Wait(); + void Wait() { + while(!signalled_) { + SleepMilliseconds(10); + } + } private: - // We cannot use Mutex here as this class is intended for testing it. - pthread_mutex_t mutex_; - pthread_cond_t cond_; - bool signalled_; + volatile bool signalled_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore); }; @@ -971,8 +985,8 @@ class ThreadStartSemaphore { // ThreadWithParam thread(&ThreadFunc, 5, &semaphore); // semaphore.Signal(); // Allows the thread to start. // -// This class is supplied only for testing Google Test's own -// constructs. Do not use it in user tests, either directly or indirectly. +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. template class ThreadWithParam { public: diff --git a/src/gtest-port.cc b/src/gtest-port.cc index 1c4c1bdc..b9504f56 100644 --- a/src/gtest-port.cc +++ b/src/gtest-port.cc @@ -75,46 +75,6 @@ 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) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); - GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_init(&cond_, NULL)); - 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_); - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); - GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_destroy(&cond_)); -} - -// Signals to all test threads to start. Must be called from the -// controlling thread. -void ThreadStartSemaphore::Signal() { - signalled_ = true; - GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_signal(&cond_)); - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); -} - -// Blocks until the controlling thread signals. Should be called from a -// test thread. -void ThreadStartSemaphore::Wait() { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); - - while (!signalled_) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_wait(&cond_, &mutex_)); - } - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); -} - -#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/test/gtest-port_test.cc b/test/gtest-port_test.cc index f7f26215..357a99ed 100644 --- a/test/gtest-port_test.cc +++ b/test/gtest-port_test.cc @@ -35,10 +35,6 @@ #include -#if GTEST_HAS_PTHREAD -#include // For nanosleep(). -#endif // GTEST_HAS_PTHREAD - #if GTEST_OS_MAC #include #endif // GTEST_OS_MAC @@ -137,10 +133,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) { if (GetThreadCount() == 1) break; - timespec time; - time.tv_sec = 0; - time.tv_nsec = 100L * 1000 * 1000; // .1 seconds. - nanosleep(&time, NULL); + SleepMilliseconds(100); } EXPECT_EQ(1U, GetThreadCount()); pthread_mutex_destroy(&mutex); @@ -802,7 +795,7 @@ TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) { } #if GTEST_IS_THREADSAFE -TEST(MutexTestDeathTest, AssertHeldShouldAssertWhenNotLocked) { +TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) { // AssertHeld() is flaky only in the presence of multiple threads accessing // the lock. In this case, the test is robust. EXPECT_DEATH_IF_SUPPORTED({ @@ -813,8 +806,10 @@ TEST(MutexTestDeathTest, AssertHeldShouldAssertWhenNotLocked) { "The current thread is not holding the mutex @.+"); } -void SleepMilliseconds(int time) { - usleep(static_cast(time * 1000.0)); +TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { + Mutex m; + MutexLock lock(&m); + m.AssertHeld(); } class AtomicCounterWithMutex { @@ -873,7 +868,7 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) { kCycleCount), &semaphore)); } - semaphore.Signal(); // Start the threads. + semaphore.Signal(); // Starts the threads. for (int i = 0; i < kThreadCount; ++i) counting_threads[i]->Join();