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).

This commit is contained in:
zhanyong.wan
2010-02-24 17:19:25 +00:00
parent dd280cfa8d
commit 3bef459eac
21 changed files with 796 additions and 119 deletions

View File

@@ -77,7 +77,7 @@ namespace testing {
namespace internal {
// Protects copying of all linked_ptr objects.
extern Mutex g_linked_ptr_mutex;
GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
// This is used internally by all instances of linked_ptr<>. It needs to be
// a non-template class because different types of linked_ptr<> can refer to

View File

@@ -343,10 +343,14 @@
#endif // GTEST_HAS_RTTI
// Determines whether <pthread.h> is available.
// Determines whether Google Test can use the pthreads library.
#ifndef GTEST_HAS_PTHREAD
// The user didn't tell us, so we need to figure it out.
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_SOLARIS)
// The user didn't tell us explicitly, so we assume pthreads support is
// available on Linux and Mac.
//
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
// to your compiler flags.
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
#endif // GTEST_HAS_PTHREAD
// Determines whether Google Test can use tr1/tuple. You can define
@@ -708,6 +712,27 @@ class GTestLog {
inline void LogToStderr() {}
inline void FlushInfoLog() { fflush(NULL); }
// INTERNAL IMPLEMENTATION - DO NOT USE.
//
// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
// is not satisfied.
// Synopsys:
// GTEST_CHECK_(boolean_condition);
// or
// GTEST_CHECK_(boolean_condition) << "Additional message";
//
// This checks the condition and if the condition is not satisfied
// it prints message about the condition violation, including the
// condition itself, plus additional message streamed into it, if any,
// and then it aborts the program. It aborts the program irrespective of
// whether it is built in the debug mode or not.
#define GTEST_CHECK_(condition) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::IsTrue(condition)) \
; \
else \
GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
#if GTEST_HAS_STREAM_REDIRECTION_
// Defines the stderr capturer:
@@ -736,6 +761,260 @@ const ::std::vector<String>& GetArgvs();
// Defines synchronization primitives.
#if GTEST_HAS_PTHREAD
// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
// true.
#include <pthread.h>
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
// are used in conjunction with class MutexLock:
//
// Mutex mutex;
// ...
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
// // of the current scope.
//
// MutexBase implements behavior for both statically and dynamically
// allocated mutexes. Do not use the MutexBase type directly. Instead,
// define a static mutex using the GTEST_DEFINE_STATIC_MUTEX_ macro:
//
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
//
// Such mutex may also be forward-declared:
//
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
//
// Do not use MutexBase for dynamic mutexes either. Use the Mutex class
// for them.
class MutexBase {
public:
void Lock();
void Unlock();
// Does nothing if the current thread holds the mutex. Otherwise, crashes
// with high probability.
void AssertHeld() const;
// We must be able to initialize objects of MutexBase used as static
// mutexes with initializer lists. This means MutexBase has to be a POD.
// The class members have to be public.
public:
pthread_mutex_t mutex_;
pthread_t owner_;
};
// Forward-declares a static mutex.
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::MutexBase mutex
// Defines and statically initializes a static mutex.
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
// The class Mutex supports only mutexes created at runtime. It shares its
// API with MutexBase otherwise.
class Mutex : public MutexBase {
public:
Mutex();
~Mutex();
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
};
// We cannot call it MutexLock directly as the ctor declaration would
// conflict with a macro named MutexLock, which is defined on some
// platforms. Hence the typedef trick below.
class GTestMutexLock {
public:
explicit GTestMutexLock(MutexBase* mutex)
: mutex_(mutex) { mutex_->Lock(); }
~GTestMutexLock() { mutex_->Unlock(); }
private:
MutexBase* const mutex_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
};
typedef GTestMutexLock MutexLock;
// Implements thread-local storage on pthreads-based systems.
//
// // Thread 1
// ThreadLocal<int> tl(100);
//
// // Thread 2
// tl.set(150);
// EXPECT_EQ(150, tl.get());
//
// // Thread 1
// EXPECT_EQ(100, tl.get()); // On Thread 1, tl.get() returns original value.
// tl.set(200);
// EXPECT_EQ(200, tl.get());
//
// The default ThreadLocal constructor requires T to have a default
// constructor. The single param constructor requires a copy contructor
// from T. A per-thread object managed by a ThreadLocal instance for a
// thread is guaranteed to exist at least until the earliest of the two
// events: (a) the thread terminates or (b) the ThreadLocal object
// managing it is destroyed.
template <typename T>
class ThreadLocal {
public:
ThreadLocal()
: key_(CreateKey()),
default_(),
instance_creator_func_(DefaultConstructNewInstance) {}
explicit ThreadLocal(const T& value)
: key_(CreateKey()),
default_(value),
instance_creator_func_(CopyConstructNewInstance) {}
~ThreadLocal() {
const int err = pthread_key_delete(key_);
GTEST_CHECK_(err == 0) << "pthread_key_delete failed with error " << err;
}
T* pointer() { return GetOrCreateValue(); }
const T* pointer() const { return GetOrCreateValue(); }
const T& get() const { return *pointer(); }
void set(const T& value) { *pointer() = value; }
private:
static pthread_key_t CreateKey() {
pthread_key_t key;
const int err = pthread_key_create(&key, &DeleteData);
GTEST_CHECK_(err == 0) << "pthread_key_create failed with error " << err;
return key;
}
T* GetOrCreateValue() const {
T* value = static_cast<T*>(pthread_getspecific(key_));
if (value == NULL) {
value = (*instance_creator_func_)(default_);
const int err = pthread_setspecific(key_, value);
GTEST_CHECK_(err == 0) << "pthread_setspecific failed with error " << err;
}
return value;
}
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.
const pthread_key_t key_;
// Contains the value that CopyConstructNewInstance copies from.
const T default_;
// Points to either DefaultConstructNewInstance or CopyConstructNewInstance.
T* (*const instance_creator_func_)(const T& default_);
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};
// Allows the controller thread pause execution of newly created test
// threads until signalled. Instances of this class must be created and
// destroyed in the controller thread.
//
// 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 ThreadStartSemaphore {
public:
ThreadStartSemaphore();
~ThreadStartSemaphore();
// Signals to all test threads created with this semaphore to start. Must
// be called from the controlling thread.
void Signal();
// Blocks until the controlling thread signals. Must be called from a test
// thread.
void Wait();
private:
// We cannot use Mutex here as this class is intended for testing it.
pthread_mutex_t mutex_;
pthread_cond_t cond_;
bool signalled_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore);
};
// Helper class for testing Google Test's multithreading constructs.
// Use:
//
// void ThreadFunc(int param) { /* Do things with param */ }
// ThreadSemaphore semaphore;
// ...
// // The semaphore parameter is optional; you can supply NULL.
// ThredWithParam<int> thread(&ThreadFunc, 5, &semaphore);
// sem.Signal(); // Allows the thread to start.
//
// 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.
template <typename T>
class ThreadWithParam {
public:
typedef void (*UserThreadFunc)(T);
ThreadWithParam(UserThreadFunc func, T param, ThreadStartSemaphore* semaphore)
: func_(func),
param_(param),
start_semaphore_(semaphore),
finished_(false) {
// func_, param_, and start_semaphore_ must be initialized before
// pthread_create() is called.
const int err = pthread_create(&thread_, 0, ThreadMainStatic, this);
GTEST_CHECK_(err == 0) << "pthread_create failed with error: "
<< strerror(err) << "(" << err << ")";
}
~ThreadWithParam() { Join(); }
void Join() {
if (!finished_) {
const int err = pthread_join(thread_, 0);
GTEST_CHECK_(err == 0) << "pthread_join failed with error:"
<< strerror(err) << "(" << err << ")";
finished_ = true;
}
}
private:
void ThreadMain() {
if (start_semaphore_ != NULL)
start_semaphore_->Wait();
func_(param_);
}
static void* ThreadMainStatic(void* param) {
static_cast<ThreadWithParam<T>*>(param)->ThreadMain();
return NULL; // We are not interested in thread exit code.
}
// User supplied thread function.
const UserThreadFunc func_;
// 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
// signals.
ThreadStartSemaphore* const start_semaphore_;
// true iff UserThreadFunc has not completed yet.
bool finished_;
};
#define GTEST_IS_THREADSAFE 1
#else // GTEST_HAS_PTHREAD
// A dummy implementation of synchronization primitives (mutex, lock,
// and thread-local variable). Necessary for compiling Google Test where
// mutex is not supported - using Google Test in multiple threads is not
@@ -744,14 +1023,14 @@ const ::std::vector<String>& GetArgvs();
class Mutex {
public:
Mutex() {}
explicit Mutex(int /*unused*/) {}
void AssertHeld() const {}
enum { NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX = 0 };
};
// We cannot call it MutexLock directly as the ctor declaration would
// conflict with a macro named MutexLock, which is defined on some
// platforms. Hence the typedef trick below.
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::Mutex mutex
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
class GTestMutexLock {
public:
explicit GTestMutexLock(Mutex*) {} // NOLINT
@@ -772,14 +1051,16 @@ class ThreadLocal {
T value_;
};
// Returns the number of threads running in the process, or 0 to indicate that
// we cannot detect it.
size_t GetThreadCount();
// The above synchronization primitives have dummy implementations.
// Therefore Google Test is not thread-safe.
#define GTEST_IS_THREADSAFE 0
#endif // GTEST_HAS_PTHREAD
// Returns the number of threads running in the process, or 0 to indicate that
// we cannot detect it.
size_t GetThreadCount();
// Passing non-POD classes through ellipsis (...) crashes the ARM
// compiler and generates a warning in Sun Studio. The Nokia Symbian
// and the IBM XL C/C++ compiler try to instantiate a copy constructor
@@ -1024,27 +1305,6 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
// Utilities for command line flags and environment variables.
// INTERNAL IMPLEMENTATION - DO NOT USE.
//
// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
// is not satisfied.
// Synopsys:
// GTEST_CHECK_(boolean_condition);
// or
// GTEST_CHECK_(boolean_condition) << "Additional message";
//
// This checks the condition and if the condition is not satisfied
// it prints message about the condition violation, including the
// condition itself, plus additional message streamed into it, if any,
// and then it aborts the program. It aborts the program irrespective of
// whether it is built in the debug mode or not.
#define GTEST_CHECK_(condition) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::IsTrue(condition)) \
; \
else \
GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
// Macro for referencing flags.
#define GTEST_FLAG(name) FLAGS_gtest_##name