|
|
@ -733,6 +733,16 @@ inline void FlushInfoLog() { fflush(NULL); } |
|
|
|
else \
|
|
|
|
else \
|
|
|
|
GTEST_LOG_(FATAL) << "Condition " #condition " failed. " |
|
|
|
GTEST_LOG_(FATAL) << "Condition " #condition " failed. " |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// An all-mode assert to verify that the given POSIX-style function
|
|
|
|
|
|
|
|
// call returns 0 (indicating success). Known limitation: this
|
|
|
|
|
|
|
|
// doesn't expand to a balanced 'if' statement, so enclose the macro
|
|
|
|
|
|
|
|
// in {} if you need to use it as the only statement in an 'if'
|
|
|
|
|
|
|
|
// branch.
|
|
|
|
|
|
|
|
#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ |
|
|
|
|
|
|
|
if (const int gtest_error = (posix_call)) \
|
|
|
|
|
|
|
|
GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
|
|
|
|
|
|
|
|
<< gtest_error |
|
|
|
|
|
|
|
|
|
|
|
#if GTEST_HAS_STREAM_REDIRECTION_ |
|
|
|
#if GTEST_HAS_STREAM_REDIRECTION_ |
|
|
|
|
|
|
|
|
|
|
|
// Defines the stderr capturer:
|
|
|
|
// Defines the stderr capturer:
|
|
|
@ -770,60 +780,81 @@ const ::std::vector<String>& GetArgvs(); |
|
|
|
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
|
|
|
|
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
|
|
|
|
// are used in conjunction with class MutexLock:
|
|
|
|
// are used in conjunction with class MutexLock:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Mutex mutex;
|
|
|
|
// Mutex mutex;
|
|
|
|
// ...
|
|
|
|
// ...
|
|
|
|
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
|
|
|
|
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
|
|
|
|
// // of the current scope.
|
|
|
|
// // of the current scope.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// MutexBase implements behavior for both statically and dynamically
|
|
|
|
// MutexBase implements behavior for both statically and dynamically
|
|
|
|
// allocated mutexes. Do not use the MutexBase type directly. Instead,
|
|
|
|
// allocated mutexes. Do not use MutexBase directly. Instead, write
|
|
|
|
// define a static mutex using the GTEST_DEFINE_STATIC_MUTEX_ macro:
|
|
|
|
// the following to define a static mutex:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
|
|
|
|
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Such mutex may also be forward-declared:
|
|
|
|
// You can forward declare a static mutex like this:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
|
|
|
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Do not use MutexBase for dynamic mutexes either. Use the Mutex class
|
|
|
|
// To create a dynamic mutex, just define an object of type Mutex.
|
|
|
|
// for them.
|
|
|
|
|
|
|
|
class MutexBase { |
|
|
|
class MutexBase { |
|
|
|
public: |
|
|
|
public: |
|
|
|
void Lock(); |
|
|
|
// Acquires this mutex.
|
|
|
|
void Unlock(); |
|
|
|
void Lock() { |
|
|
|
|
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); |
|
|
|
|
|
|
|
owner_ = pthread_self(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Releases this mutex.
|
|
|
|
|
|
|
|
void 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; |
|
|
|
|
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
|
|
|
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
|
|
|
// with high probability.
|
|
|
|
// with high probability.
|
|
|
|
void AssertHeld() const; |
|
|
|
void AssertHeld() const { |
|
|
|
|
|
|
|
GTEST_CHECK_(owner_ == pthread_self()) |
|
|
|
|
|
|
|
<< "The current thread is not holding the mutex @" << this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// We must be able to initialize objects of MutexBase used as static
|
|
|
|
// A static mutex may be used before main() is entered. It may even
|
|
|
|
// mutexes with initializer lists. This means MutexBase has to be a POD.
|
|
|
|
// be used before the dynamic initialization stage. Therefore we
|
|
|
|
// The class members have to be public.
|
|
|
|
// must be able to initialize a static mutex object at link time.
|
|
|
|
|
|
|
|
// This means MutexBase has to be a POD and its member variables
|
|
|
|
|
|
|
|
// have to be public.
|
|
|
|
public: |
|
|
|
public: |
|
|
|
pthread_mutex_t mutex_; |
|
|
|
pthread_mutex_t mutex_; // The underlying pthread mutex.
|
|
|
|
pthread_t owner_; |
|
|
|
pthread_t owner_; // The thread holding the mutex; 0 means no one holds it.
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Forward-declares a static mutex.
|
|
|
|
// Forward-declares a static mutex.
|
|
|
|
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ |
|
|
|
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ |
|
|
|
extern ::testing::internal::MutexBase mutex |
|
|
|
extern ::testing::internal::MutexBase mutex |
|
|
|
|
|
|
|
|
|
|
|
// Defines and statically initializes a static mutex.
|
|
|
|
// Defines and statically (i.e. at link time) initializes a static mutex.
|
|
|
|
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ |
|
|
|
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ |
|
|
|
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 } |
|
|
|
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 } |
|
|
|
|
|
|
|
|
|
|
|
// The class Mutex supports only mutexes created at runtime. It shares its
|
|
|
|
// The Mutex class can only be used for mutexes created at runtime. It
|
|
|
|
// API with MutexBase otherwise.
|
|
|
|
// shares its API with MutexBase otherwise.
|
|
|
|
class Mutex : public MutexBase { |
|
|
|
class Mutex : public MutexBase { |
|
|
|
public: |
|
|
|
public: |
|
|
|
Mutex(); |
|
|
|
Mutex() { |
|
|
|
~Mutex(); |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); |
|
|
|
|
|
|
|
owner_ = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
~Mutex() { |
|
|
|
|
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); |
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// We cannot call it MutexLock directly as the ctor declaration would
|
|
|
|
// We cannot name this class MutexLock as the ctor declaration would
|
|
|
|
// conflict with a macro named MutexLock, which is defined on some
|
|
|
|
// conflict with a macro named MutexLock, which is defined on some
|
|
|
|
// platforms. Hence the typedef trick below.
|
|
|
|
// platforms. Hence the typedef trick below.
|
|
|
|
class GTestMutexLock { |
|
|
|
class GTestMutexLock { |
|
|
@ -843,40 +874,34 @@ typedef GTestMutexLock MutexLock; |
|
|
|
|
|
|
|
|
|
|
|
// Implements thread-local storage on pthreads-based systems.
|
|
|
|
// Implements thread-local storage on pthreads-based systems.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// // Thread 1
|
|
|
|
// // Thread 1
|
|
|
|
// ThreadLocal<int> tl(100);
|
|
|
|
// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// // Thread 2
|
|
|
|
// // Thread 2
|
|
|
|
// tl.set(150);
|
|
|
|
// tl.set(150); // Changes the value for thread 2 only.
|
|
|
|
// EXPECT_EQ(150, tl.get());
|
|
|
|
// EXPECT_EQ(150, tl.get());
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// // Thread 1
|
|
|
|
// // Thread 1
|
|
|
|
// EXPECT_EQ(100, tl.get()); // On Thread 1, tl.get() returns original value.
|
|
|
|
// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
|
|
|
|
// tl.set(200);
|
|
|
|
// tl.set(200);
|
|
|
|
// EXPECT_EQ(200, tl.get());
|
|
|
|
// EXPECT_EQ(200, tl.get());
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// The default ThreadLocal constructor requires T to have a default
|
|
|
|
// The template type argument T must have a public copy constructor.
|
|
|
|
// constructor. The single param constructor requires a copy contructor
|
|
|
|
// In addition, the default ThreadLocal constructor requires T to have
|
|
|
|
// from T. A per-thread object managed by a ThreadLocal instance for a
|
|
|
|
// a public default constructor. An object managed by a ThreadLocal
|
|
|
|
// thread is guaranteed to exist at least until the earliest of the two
|
|
|
|
// instance for a thread is guaranteed to exist at least until the
|
|
|
|
// events: (a) the thread terminates or (b) the ThreadLocal object
|
|
|
|
// earliest of the two events: (a) the thread terminates or (b) the
|
|
|
|
// managing it is destroyed.
|
|
|
|
// ThreadLocal object is destroyed.
|
|
|
|
template <typename T> |
|
|
|
template <typename T> |
|
|
|
class ThreadLocal { |
|
|
|
class ThreadLocal { |
|
|
|
public: |
|
|
|
public: |
|
|
|
ThreadLocal() |
|
|
|
ThreadLocal() : key_(CreateKey()), |
|
|
|
: key_(CreateKey()), |
|
|
|
default_() {} |
|
|
|
default_(), |
|
|
|
explicit ThreadLocal(const T& value) : key_(CreateKey()), |
|
|
|
instance_creator_func_(DefaultConstructNewInstance) {} |
|
|
|
default_(value) {} |
|
|
|
|
|
|
|
|
|
|
|
explicit ThreadLocal(const T& value) |
|
|
|
|
|
|
|
: key_(CreateKey()), |
|
|
|
|
|
|
|
default_(value), |
|
|
|
|
|
|
|
instance_creator_func_(CopyConstructNewInstance) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~ThreadLocal() { |
|
|
|
~ThreadLocal() { |
|
|
|
const int err = pthread_key_delete(key_); |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); |
|
|
|
GTEST_CHECK_(err == 0) << "pthread_key_delete failed with error " << err; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T* pointer() { return GetOrCreateValue(); } |
|
|
|
T* pointer() { return GetOrCreateValue(); } |
|
|
@ -887,54 +912,43 @@ class ThreadLocal { |
|
|
|
private: |
|
|
|
private: |
|
|
|
static pthread_key_t CreateKey() { |
|
|
|
static pthread_key_t CreateKey() { |
|
|
|
pthread_key_t key; |
|
|
|
pthread_key_t key; |
|
|
|
const int err = pthread_key_create(&key, &DeleteData); |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_key_create(&key, &DeleteData)); |
|
|
|
GTEST_CHECK_(err == 0) << "pthread_key_create failed with error " << err; |
|
|
|
|
|
|
|
return key; |
|
|
|
return key; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T* GetOrCreateValue() const { |
|
|
|
T* GetOrCreateValue() const { |
|
|
|
T* value = static_cast<T*>(pthread_getspecific(key_)); |
|
|
|
T* const value = static_cast<T*>(pthread_getspecific(key_)); |
|
|
|
if (value == NULL) { |
|
|
|
if (value != NULL) |
|
|
|
value = (*instance_creator_func_)(default_); |
|
|
|
return value; |
|
|
|
const int err = pthread_setspecific(key_, value); |
|
|
|
|
|
|
|
GTEST_CHECK_(err == 0) << "pthread_setspecific failed with error " << err; |
|
|
|
T* const new_value = new T(default_); |
|
|
|
} |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, new_value)); |
|
|
|
return value; |
|
|
|
return new_value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void DeleteData(void* data) { delete static_cast<T*>(data); } |
|
|
|
static void DeleteData(void* data) { delete static_cast<T*>(data); } |
|
|
|
|
|
|
|
|
|
|
|
static T* DefaultConstructNewInstance(const T&) { return new T(); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Copy constructs new instance of T from default_. Will not be
|
|
|
|
|
|
|
|
// instantiated unless this ThreadLocal is constructed by the single
|
|
|
|
|
|
|
|
// parameter constructor.
|
|
|
|
|
|
|
|
static T* CopyConstructNewInstance(const T& t) { return new T(t); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A key pthreads uses for looking up per-thread values.
|
|
|
|
// A key pthreads uses for looking up per-thread values.
|
|
|
|
const pthread_key_t key_; |
|
|
|
const pthread_key_t key_; |
|
|
|
// Contains the value that CopyConstructNewInstance copies from.
|
|
|
|
const T default_; // The default value for each thread.
|
|
|
|
const T default_; |
|
|
|
|
|
|
|
// Points to either DefaultConstructNewInstance or CopyConstructNewInstance.
|
|
|
|
|
|
|
|
T* (*const instance_creator_func_)(const T& default_); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); |
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Allows the controller thread pause execution of newly created test
|
|
|
|
// Allows a controller thread to pause execution of newly created
|
|
|
|
// threads until signalled. Instances of this class must be created and
|
|
|
|
// threads until signalled. Instances of this class must be created
|
|
|
|
// destroyed in the controller thread.
|
|
|
|
// and destroyed in the controller thread.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// This class is supplied only for the purpose of testing Google Test's own
|
|
|
|
// This class is supplied only for testing Google Test's own
|
|
|
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
|
|
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
|
|
|
class ThreadStartSemaphore { |
|
|
|
class ThreadStartSemaphore { |
|
|
|
public: |
|
|
|
public: |
|
|
|
ThreadStartSemaphore(); |
|
|
|
ThreadStartSemaphore(); |
|
|
|
~ThreadStartSemaphore(); |
|
|
|
~ThreadStartSemaphore(); |
|
|
|
// Signals to all test threads created with this semaphore to start. Must
|
|
|
|
// Signals to all threads created with this semaphore to start. Must
|
|
|
|
// be called from the controlling thread.
|
|
|
|
// be called from the controller thread.
|
|
|
|
void Signal(); |
|
|
|
void Signal(); |
|
|
|
// Blocks until the controlling thread signals. Must be called from a test
|
|
|
|
// Blocks until the controller thread signals. Must be called from a test
|
|
|
|
// thread.
|
|
|
|
// thread.
|
|
|
|
void Wait(); |
|
|
|
void Wait(); |
|
|
|
|
|
|
|
|
|
|
@ -947,17 +961,17 @@ class ThreadStartSemaphore { |
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore); |
|
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Helper class for testing Google Test's multithreading constructs.
|
|
|
|
// Helper class for testing Google Test's multi-threading constructs.
|
|
|
|
// Use:
|
|
|
|
// Use:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// void ThreadFunc(int param) { /* Do things with param */ }
|
|
|
|
// void ThreadFunc(int param) { /* Do things with param */ }
|
|
|
|
// ThreadSemaphore semaphore;
|
|
|
|
// ThreadStartSemaphore semaphore;
|
|
|
|
// ...
|
|
|
|
// ...
|
|
|
|
// // The semaphore parameter is optional; you can supply NULL.
|
|
|
|
// // The semaphore parameter is optional; you can supply NULL.
|
|
|
|
// ThredWithParam<int> thread(&ThreadFunc, 5, &semaphore);
|
|
|
|
// ThreadWithParam<int> thread(&ThreadFunc, 5, &semaphore);
|
|
|
|
// sem.Signal(); // Allows the thread to start.
|
|
|
|
// semaphore.Signal(); // Allows the thread to start.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// This class is supplied only for the purpose of testing Google Test's own
|
|
|
|
// This class is supplied only for testing Google Test's own
|
|
|
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
|
|
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
|
|
|
template <typename T> |
|
|
|
template <typename T> |
|
|
|
class ThreadWithParam { |
|
|
|
class ThreadWithParam { |
|
|
@ -969,19 +983,16 @@ class ThreadWithParam { |
|
|
|
param_(param), |
|
|
|
param_(param), |
|
|
|
start_semaphore_(semaphore), |
|
|
|
start_semaphore_(semaphore), |
|
|
|
finished_(false) { |
|
|
|
finished_(false) { |
|
|
|
// func_, param_, and start_semaphore_ must be initialized before
|
|
|
|
// The thread can be created only after all fields except thread_
|
|
|
|
// pthread_create() is called.
|
|
|
|
// have been initialized.
|
|
|
|
const int err = pthread_create(&thread_, 0, ThreadMainStatic, this); |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_( |
|
|
|
GTEST_CHECK_(err == 0) << "pthread_create failed with error: " |
|
|
|
pthread_create(&thread_, 0, ThreadMainStatic, this)); |
|
|
|
<< strerror(err) << "(" << err << ")"; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
~ThreadWithParam() { Join(); } |
|
|
|
~ThreadWithParam() { Join(); } |
|
|
|
|
|
|
|
|
|
|
|
void Join() { |
|
|
|
void Join() { |
|
|
|
if (!finished_) { |
|
|
|
if (!finished_) { |
|
|
|
const int err = pthread_join(thread_, 0); |
|
|
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); |
|
|
|
GTEST_CHECK_(err == 0) << "pthread_join failed with error:" |
|
|
|
|
|
|
|
<< strerror(err) << "(" << err << ")"; |
|
|
|
|
|
|
|
finished_ = true; |
|
|
|
finished_ = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -992,23 +1003,18 @@ class ThreadWithParam { |
|
|
|
start_semaphore_->Wait(); |
|
|
|
start_semaphore_->Wait(); |
|
|
|
func_(param_); |
|
|
|
func_(param_); |
|
|
|
} |
|
|
|
} |
|
|
|
static void* ThreadMainStatic(void* param) { |
|
|
|
static void* ThreadMainStatic(void* thread_with_param) { |
|
|
|
static_cast<ThreadWithParam<T>*>(param)->ThreadMain(); |
|
|
|
static_cast<ThreadWithParam<T>*>(thread_with_param)->ThreadMain(); |
|
|
|
return NULL; // We are not interested in thread exit code.
|
|
|
|
return NULL; // We are not interested in the thread exit code.
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// User supplied thread function.
|
|
|
|
const UserThreadFunc func_; // User-supplied thread function.
|
|
|
|
const UserThreadFunc func_; |
|
|
|
const T param_; // User-supplied parameter to the thread function.
|
|
|
|
// User supplied parameter to UserThreadFunc.
|
|
|
|
|
|
|
|
const T param_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Native thread object.
|
|
|
|
|
|
|
|
pthread_t thread_; |
|
|
|
|
|
|
|
// When non-NULL, used to block execution until the controller thread
|
|
|
|
// When non-NULL, used to block execution until the controller thread
|
|
|
|
// signals.
|
|
|
|
// signals.
|
|
|
|
ThreadStartSemaphore* const start_semaphore_; |
|
|
|
ThreadStartSemaphore* const start_semaphore_; |
|
|
|
// true iff UserThreadFunc has not completed yet.
|
|
|
|
bool finished_; // Has the thread function finished?
|
|
|
|
bool finished_; |
|
|
|
pthread_t thread_; // The native thread object.
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#define GTEST_IS_THREADSAFE 1 |
|
|
|
#define GTEST_IS_THREADSAFE 1 |
|
|
|