Commit 4879aac7 by zhanyong.wan

Simplifies the threading implementation and improves some comments.

parent 0d27868d
...@@ -81,10 +81,8 @@ const int kStdErrFileno = STDERR_FILENO; ...@@ -81,10 +81,8 @@ const int kStdErrFileno = STDERR_FILENO;
// newly created test threads until signalled. Instances of this class must // newly created test threads until signalled. Instances of this class must
// be created and destroyed in the controller thread. // be created and destroyed in the controller thread.
ThreadStartSemaphore::ThreadStartSemaphore() : signalled_(false) { ThreadStartSemaphore::ThreadStartSemaphore() : signalled_(false) {
int err = pthread_mutex_init(&mutex_, NULL); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err; GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_init(&cond_, NULL));
err = pthread_cond_init(&cond_, NULL);
GTEST_CHECK_(err == 0) << "pthread_cond_init failed with error " << err;
pthread_mutex_lock(&mutex_); pthread_mutex_lock(&mutex_);
} }
...@@ -92,75 +90,29 @@ ThreadStartSemaphore::~ThreadStartSemaphore() { ...@@ -92,75 +90,29 @@ ThreadStartSemaphore::~ThreadStartSemaphore() {
// Every ThreadStartSemaphore object must be signalled. It locks // Every ThreadStartSemaphore object must be signalled. It locks
// internal mutex upon creation and Signal unlocks it. // internal mutex upon creation and Signal unlocks it.
GTEST_CHECK_(signalled_); GTEST_CHECK_(signalled_);
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
int err = pthread_mutex_destroy(&mutex_); GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_destroy(&cond_));
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 // Signals to all test threads to start. Must be called from the
// controlling thread. // controlling thread.
void ThreadStartSemaphore::Signal() { void ThreadStartSemaphore::Signal() {
signalled_ = true; signalled_ = true;
int err = pthread_cond_signal(&cond_); GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_signal(&cond_));
GTEST_CHECK_(err == 0) GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
<< "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 // Blocks until the controlling thread signals. Should be called from a
// test thread. // test thread.
void ThreadStartSemaphore::Wait() { void ThreadStartSemaphore::Wait() {
int err = pthread_mutex_lock(&mutex_); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err;
while (!signalled_) { while (!signalled_) {
err = pthread_cond_wait(&cond_, &mutex_); GTEST_CHECK_POSIX_SUCCESS_(pthread_cond_wait(&cond_, &mutex_));
GTEST_CHECK_(err == 0)
<< "pthread_cond_wait failed with error " << err;
} }
err = pthread_mutex_unlock(&mutex_); GTEST_CHECK_POSIX_SUCCESS_(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 #endif // GTEST_HAS_PTHREAD
#if GTEST_OS_MAC #if GTEST_OS_MAC
......
...@@ -770,18 +770,6 @@ TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) { ...@@ -770,18 +770,6 @@ TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
EXPECT_EQ(&i, t2.get()); EXPECT_EQ(&i, t2.get());
} }
class NoCopyConstructor {
public:
NoCopyConstructor() {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(NoCopyConstructor);
};
TEST(ThreadLocalTest, ValueCopyConstructorIsNotRequiredForDefaultVersion) {
ThreadLocal<NoCopyConstructor> bar;
bar.get();
}
class NoDefaultContructor { class NoDefaultContructor {
public: public:
explicit NoDefaultContructor(const char*) {} explicit NoDefaultContructor(const char*) {}
...@@ -796,9 +784,6 @@ TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) { ...@@ -796,9 +784,6 @@ TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
TEST(ThreadLocalTest, GetAndPointerReturnSameValue) { TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
ThreadLocal<String> thread_local; ThreadLocal<String> thread_local;
// This is why EXPECT_TRUE is used here rather than EXPECT_EQ because
// we don't care about a particular value of thread_local.pointer() here;
// we only care about pointer and reference referring to the same lvalue.
EXPECT_EQ(thread_local.pointer(), &(thread_local.get())); EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
// Verifies the condition still holds after calling set. // Verifies the condition still holds after calling set.
...@@ -825,7 +810,7 @@ TEST(MutexTestDeathTest, AssertHeldShouldAssertWhenNotLocked) { ...@@ -825,7 +810,7 @@ TEST(MutexTestDeathTest, AssertHeldShouldAssertWhenNotLocked) {
{ MutexLock lock(&m); } { MutexLock lock(&m); }
m.AssertHeld(); m.AssertHeld();
}, },
"Current thread is not holding mutex..+"); "The current thread is not holding the mutex @.+");
} }
void SleepMilliseconds(int time) { void SleepMilliseconds(int time) {
...@@ -847,16 +832,13 @@ class AtomicCounterWithMutex { ...@@ -847,16 +832,13 @@ class AtomicCounterWithMutex {
// We cannot use Mutex and MutexLock here or rely on their memory // We cannot use Mutex and MutexLock here or rely on their memory
// barrier functionality as we are testing them here. // barrier functionality as we are testing them here.
pthread_mutex_t memory_barrier_mutex; pthread_mutex_t memory_barrier_mutex;
int err = pthread_mutex_init(&memory_barrier_mutex, NULL); GTEST_CHECK_POSIX_SUCCESS_(
GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err; pthread_mutex_init(&memory_barrier_mutex, NULL));
err = pthread_mutex_lock(&memory_barrier_mutex); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err;
SleepMilliseconds(random_.Generate(30)); SleepMilliseconds(random_.Generate(30));
err = pthread_mutex_unlock(&memory_barrier_mutex); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
GTEST_CHECK_(err == 0)
<< "pthread_mutex_unlock failed with error " << err;
} }
value_ = temp + 1; value_ = temp + 1;
} }
...@@ -937,7 +919,7 @@ int CountedDestructor::counter_ = 0; ...@@ -937,7 +919,7 @@ int CountedDestructor::counter_ = 0;
template <typename T> template <typename T>
void CallThreadLocalGet(ThreadLocal<T>* threadLocal) { void CallThreadLocalGet(ThreadLocal<T>* threadLocal) {
threadLocal->get(); threadLocal->get();
} }
TEST(ThreadLocalTest, DestroysManagedObjectsNoLaterThanSelf) { TEST(ThreadLocalTest, DestroysManagedObjectsNoLaterThanSelf) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment