Such style. (Code style unification)
This commit is contained in:
parent
57bcd8f25c
commit
8c01ec8897
57 changed files with 6548 additions and 6437 deletions
779
lib/tinythread.h
779
lib/tinythread.h
|
@ -57,30 +57,30 @@ freely, subject to the following restrictions:
|
|||
|
||||
// Which platform are we on?
|
||||
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||
#define _TTHREAD_WIN32_
|
||||
#else
|
||||
#define _TTHREAD_POSIX_
|
||||
#endif
|
||||
#define _TTHREAD_PLATFORM_DEFINED_
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||
#define _TTHREAD_WIN32_
|
||||
#else
|
||||
#define _TTHREAD_POSIX_
|
||||
#endif
|
||||
#define _TTHREAD_PLATFORM_DEFINED_
|
||||
#endif
|
||||
|
||||
// Platform specific includes
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#ifdef __UNDEF_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#ifdef __UNDEF_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Generic includes
|
||||
|
@ -95,23 +95,23 @@ freely, subject to the following restrictions:
|
|||
|
||||
// Do we have a fully featured C++11 compiler?
|
||||
#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
|
||||
#define _TTHREAD_CPP11_
|
||||
#define _TTHREAD_CPP11_
|
||||
#endif
|
||||
|
||||
// ...at least partial C++11?
|
||||
#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
|
||||
#define _TTHREAD_CPP11_PARTIAL_
|
||||
#define _TTHREAD_CPP11_PARTIAL_
|
||||
#endif
|
||||
|
||||
// Macro for disabling assignments of objects.
|
||||
#ifdef _TTHREAD_CPP11_PARTIAL_
|
||||
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
|
||||
name(const name&) = delete; \
|
||||
name& operator=(const name&) = delete;
|
||||
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
|
||||
name(const name&) = delete; \
|
||||
name& operator=(const name&) = delete;
|
||||
#else
|
||||
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
|
||||
name(const name&); \
|
||||
name& operator=(const name&);
|
||||
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
|
||||
name(const name&); \
|
||||
name& operator=(const name&);
|
||||
#endif
|
||||
|
||||
/// @def thread_local
|
||||
|
@ -136,11 +136,11 @@ freely, subject to the following restrictions:
|
|||
/// @hideinitializer
|
||||
|
||||
#if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#define thread_local __thread
|
||||
#else
|
||||
#define thread_local __declspec(thread)
|
||||
#endif
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#define thread_local __thread
|
||||
#else
|
||||
#define thread_local __declspec(thread)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -156,91 +156,86 @@ namespace tthread {
|
|||
/// program may deadlock if the thread that owns a mutex object calls lock()
|
||||
/// on that object).
|
||||
/// @see recursive_mutex
|
||||
class mutex {
|
||||
public:
|
||||
/// Constructor.
|
||||
mutex()
|
||||
class mutex {
|
||||
public:
|
||||
/// Constructor.
|
||||
mutex()
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
: mAlreadyLocked(false)
|
||||
: mAlreadyLocked(false)
|
||||
#endif
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
InitializeCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_init(&mHandle, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~mutex()
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
DeleteCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_destroy(&mHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Lock the mutex.
|
||||
/// The method will block the calling thread until a lock on the mutex can
|
||||
/// be obtained. The mutex remains locked until @c unlock() is called.
|
||||
/// @see lock_guard
|
||||
inline void lock()
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
EnterCriticalSection(&mHandle);
|
||||
while(mAlreadyLocked) Sleep(1000); // Simulate deadlock...
|
||||
mAlreadyLocked = true;
|
||||
#else
|
||||
pthread_mutex_lock(&mHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Try to lock the mutex.
|
||||
/// The method will try to lock the mutex. If it fails, the function will
|
||||
/// return immediately (non-blocking).
|
||||
/// @return @c true if the lock was acquired, or @c false if the lock could
|
||||
/// not be acquired.
|
||||
inline bool try_lock()
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
|
||||
if(ret && mAlreadyLocked)
|
||||
{
|
||||
LeaveCriticalSection(&mHandle);
|
||||
ret = false;
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
InitializeCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_init(&mHandle, NULL);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Unlock the mutex.
|
||||
/// If any threads are waiting for the lock on this mutex, one of them will
|
||||
/// be unblocked.
|
||||
inline void unlock()
|
||||
{
|
||||
/// Destructor.
|
||||
~mutex() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
mAlreadyLocked = false;
|
||||
LeaveCriticalSection(&mHandle);
|
||||
DeleteCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_unlock(&mHandle);
|
||||
pthread_mutex_destroy(&mHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(mutex)
|
||||
|
||||
private:
|
||||
/// Lock the mutex.
|
||||
/// The method will block the calling thread until a lock on the mutex can
|
||||
/// be obtained. The mutex remains locked until @c unlock() is called.
|
||||
/// @see lock_guard
|
||||
inline void lock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
CRITICAL_SECTION mHandle;
|
||||
bool mAlreadyLocked;
|
||||
EnterCriticalSection(&mHandle);
|
||||
while (mAlreadyLocked) Sleep(1000); // Simulate deadlock...
|
||||
mAlreadyLocked = true;
|
||||
#else
|
||||
pthread_mutex_t mHandle;
|
||||
pthread_mutex_lock(&mHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Try to lock the mutex.
|
||||
/// The method will try to lock the mutex. If it fails, the function will
|
||||
/// return immediately (non-blocking).
|
||||
/// @return @c true if the lock was acquired, or @c false if the lock could
|
||||
/// not be acquired.
|
||||
inline bool try_lock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
|
||||
if (ret && mAlreadyLocked) {
|
||||
LeaveCriticalSection(&mHandle);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Unlock the mutex.
|
||||
/// If any threads are waiting for the lock on this mutex, one of them will
|
||||
/// be unblocked.
|
||||
inline void unlock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
mAlreadyLocked = false;
|
||||
LeaveCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_unlock(&mHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(mutex)
|
||||
|
||||
private:
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
CRITICAL_SECTION mHandle;
|
||||
bool mAlreadyLocked;
|
||||
#else
|
||||
pthread_mutex_t mHandle;
|
||||
#endif
|
||||
|
||||
friend class condition_variable;
|
||||
};
|
||||
friend class condition_variable;
|
||||
};
|
||||
|
||||
/// Recursive mutex class.
|
||||
/// This is a mutual exclusion object for synchronizing access to shared
|
||||
|
@ -248,81 +243,76 @@ class mutex {
|
|||
/// may lock the mutex several times, as long as it unlocks the mutex the same
|
||||
/// number of times).
|
||||
/// @see mutex
|
||||
class recursive_mutex {
|
||||
public:
|
||||
/// Constructor.
|
||||
recursive_mutex()
|
||||
{
|
||||
class recursive_mutex {
|
||||
public:
|
||||
/// Constructor.
|
||||
recursive_mutex() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
InitializeCriticalSection(&mHandle);
|
||||
InitializeCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mHandle, &attr);
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mHandle, &attr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~recursive_mutex()
|
||||
{
|
||||
/// Destructor.
|
||||
~recursive_mutex() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
DeleteCriticalSection(&mHandle);
|
||||
DeleteCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_destroy(&mHandle);
|
||||
pthread_mutex_destroy(&mHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Lock the mutex.
|
||||
/// The method will block the calling thread until a lock on the mutex can
|
||||
/// be obtained. The mutex remains locked until @c unlock() is called.
|
||||
/// @see lock_guard
|
||||
inline void lock()
|
||||
{
|
||||
/// Lock the mutex.
|
||||
/// The method will block the calling thread until a lock on the mutex can
|
||||
/// be obtained. The mutex remains locked until @c unlock() is called.
|
||||
/// @see lock_guard
|
||||
inline void lock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
EnterCriticalSection(&mHandle);
|
||||
EnterCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_lock(&mHandle);
|
||||
pthread_mutex_lock(&mHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to lock the mutex.
|
||||
/// The method will try to lock the mutex. If it fails, the function will
|
||||
/// return immediately (non-blocking).
|
||||
/// @return @c true if the lock was acquired, or @c false if the lock could
|
||||
/// not be acquired.
|
||||
inline bool try_lock()
|
||||
{
|
||||
/// Try to lock the mutex.
|
||||
/// The method will try to lock the mutex. If it fails, the function will
|
||||
/// return immediately (non-blocking).
|
||||
/// @return @c true if the lock was acquired, or @c false if the lock could
|
||||
/// not be acquired.
|
||||
inline bool try_lock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return TryEnterCriticalSection(&mHandle) ? true : false;
|
||||
return TryEnterCriticalSection(&mHandle) ? true : false;
|
||||
#else
|
||||
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
|
||||
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlock the mutex.
|
||||
/// If any threads are waiting for the lock on this mutex, one of them will
|
||||
/// be unblocked.
|
||||
inline void unlock()
|
||||
{
|
||||
/// Unlock the mutex.
|
||||
/// If any threads are waiting for the lock on this mutex, one of them will
|
||||
/// be unblocked.
|
||||
inline void unlock() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
LeaveCriticalSection(&mHandle);
|
||||
LeaveCriticalSection(&mHandle);
|
||||
#else
|
||||
pthread_mutex_unlock(&mHandle);
|
||||
pthread_mutex_unlock(&mHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
|
||||
|
||||
private:
|
||||
private:
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
CRITICAL_SECTION mHandle;
|
||||
CRITICAL_SECTION mHandle;
|
||||
#else
|
||||
pthread_mutex_t mHandle;
|
||||
pthread_mutex_t mHandle;
|
||||
#endif
|
||||
|
||||
friend class condition_variable;
|
||||
};
|
||||
friend class condition_variable;
|
||||
};
|
||||
|
||||
/// Lock guard class.
|
||||
/// The constructor locks the mutex, and the destructor unlocks the mutex, so
|
||||
|
@ -339,30 +329,28 @@ class recursive_mutex {
|
|||
/// }
|
||||
/// @endcode
|
||||
|
||||
template <class T>
|
||||
class lock_guard {
|
||||
public:
|
||||
typedef T mutex_type;
|
||||
template <class T>
|
||||
class lock_guard {
|
||||
public:
|
||||
typedef T mutex_type;
|
||||
|
||||
lock_guard() : mMutex(0) {}
|
||||
lock_guard() : mMutex(0) {}
|
||||
|
||||
/// The constructor locks the mutex.
|
||||
explicit lock_guard(mutex_type &aMutex)
|
||||
{
|
||||
mMutex = &aMutex;
|
||||
mMutex->lock();
|
||||
}
|
||||
/// The constructor locks the mutex.
|
||||
explicit lock_guard(mutex_type & aMutex) {
|
||||
mMutex = &aMutex;
|
||||
mMutex->lock();
|
||||
}
|
||||
|
||||
/// The destructor unlocks the mutex.
|
||||
~lock_guard()
|
||||
{
|
||||
if(mMutex)
|
||||
mMutex->unlock();
|
||||
}
|
||||
/// The destructor unlocks the mutex.
|
||||
~lock_guard() {
|
||||
if (mMutex)
|
||||
mMutex->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
mutex_type * mMutex;
|
||||
};
|
||||
private:
|
||||
mutex_type * mMutex;
|
||||
};
|
||||
|
||||
/// Condition variable class.
|
||||
/// This is a signalling object for synchronizing the execution flow for
|
||||
|
@ -389,323 +377,308 @@ class lock_guard {
|
|||
/// cond.notify_all();
|
||||
/// }
|
||||
/// @endcode
|
||||
class condition_variable {
|
||||
public:
|
||||
/// Constructor.
|
||||
class condition_variable {
|
||||
public:
|
||||
/// Constructor.
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
condition_variable();
|
||||
condition_variable();
|
||||
#else
|
||||
condition_variable()
|
||||
{
|
||||
pthread_cond_init(&mHandle, NULL);
|
||||
}
|
||||
condition_variable() {
|
||||
pthread_cond_init(&mHandle, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Destructor.
|
||||
/// Destructor.
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
~condition_variable();
|
||||
~condition_variable();
|
||||
#else
|
||||
~condition_variable()
|
||||
{
|
||||
pthread_cond_destroy(&mHandle);
|
||||
}
|
||||
~condition_variable() {
|
||||
pthread_cond_destroy(&mHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Wait for the condition.
|
||||
/// The function will block the calling thread until the condition variable
|
||||
/// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
|
||||
/// @param[in] aMutex A mutex that will be unlocked when the wait operation
|
||||
/// starts, an locked again as soon as the wait operation is finished.
|
||||
template <class _mutexT>
|
||||
inline void wait(_mutexT &aMutex)
|
||||
{
|
||||
/// Wait for the condition.
|
||||
/// The function will block the calling thread until the condition variable
|
||||
/// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
|
||||
/// @param[in] aMutex A mutex that will be unlocked when the wait operation
|
||||
/// starts, an locked again as soon as the wait operation is finished.
|
||||
template <class _mutexT>
|
||||
inline void wait(_mutexT & aMutex) {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
// Increment number of waiters
|
||||
EnterCriticalSection(&mWaitersCountLock);
|
||||
++ mWaitersCount;
|
||||
LeaveCriticalSection(&mWaitersCountLock);
|
||||
// Increment number of waiters
|
||||
EnterCriticalSection(&mWaitersCountLock);
|
||||
++ mWaitersCount;
|
||||
LeaveCriticalSection(&mWaitersCountLock);
|
||||
|
||||
// Release the mutex while waiting for the condition (will decrease
|
||||
// the number of waiters when done)...
|
||||
aMutex.unlock();
|
||||
_wait();
|
||||
aMutex.lock();
|
||||
// Release the mutex while waiting for the condition (will decrease
|
||||
// the number of waiters when done)...
|
||||
aMutex.unlock();
|
||||
_wait();
|
||||
aMutex.lock();
|
||||
#else
|
||||
pthread_cond_wait(&mHandle, &aMutex.mHandle);
|
||||
pthread_cond_wait(&mHandle, &aMutex.mHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Notify one thread that is waiting for the condition.
|
||||
/// If at least one thread is blocked waiting for this condition variable,
|
||||
/// one will be woken up.
|
||||
/// @note Only threads that started waiting prior to this call will be
|
||||
/// woken up.
|
||||
/// Notify one thread that is waiting for the condition.
|
||||
/// If at least one thread is blocked waiting for this condition variable,
|
||||
/// one will be woken up.
|
||||
/// @note Only threads that started waiting prior to this call will be
|
||||
/// woken up.
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
void notify_one();
|
||||
void notify_one();
|
||||
#else
|
||||
inline void notify_one()
|
||||
{
|
||||
pthread_cond_signal(&mHandle);
|
||||
}
|
||||
inline void notify_one() {
|
||||
pthread_cond_signal(&mHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Notify all threads that are waiting for the condition.
|
||||
/// All threads that are blocked waiting for this condition variable will
|
||||
/// be woken up.
|
||||
/// @note Only threads that started waiting prior to this call will be
|
||||
/// woken up.
|
||||
/// Notify all threads that are waiting for the condition.
|
||||
/// All threads that are blocked waiting for this condition variable will
|
||||
/// be woken up.
|
||||
/// @note Only threads that started waiting prior to this call will be
|
||||
/// woken up.
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
void notify_all();
|
||||
void notify_all();
|
||||
#else
|
||||
inline void notify_all()
|
||||
{
|
||||
pthread_cond_broadcast(&mHandle);
|
||||
}
|
||||
inline void notify_all() {
|
||||
pthread_cond_broadcast(&mHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
|
||||
|
||||
private:
|
||||
private:
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
void _wait();
|
||||
HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs.
|
||||
unsigned int mWaitersCount; ///< Count of the number of waiters.
|
||||
CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
|
||||
void _wait();
|
||||
HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs.
|
||||
unsigned int mWaitersCount; ///< Count of the number of waiters.
|
||||
CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
|
||||
#else
|
||||
pthread_cond_t mHandle;
|
||||
pthread_cond_t mHandle;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/// Thread class.
|
||||
class thread {
|
||||
public:
|
||||
class thread {
|
||||
public:
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
typedef HANDLE native_handle_type;
|
||||
typedef HANDLE native_handle_type;
|
||||
#else
|
||||
typedef pthread_t native_handle_type;
|
||||
typedef pthread_t native_handle_type;
|
||||
#endif
|
||||
|
||||
class id;
|
||||
class id;
|
||||
|
||||
/// Default constructor.
|
||||
/// Construct a @c thread object without an associated thread of execution
|
||||
/// (i.e. non-joinable).
|
||||
thread() : mHandle(0), mNotAThread(true)
|
||||
/// Default constructor.
|
||||
/// Construct a @c thread object without an associated thread of execution
|
||||
/// (i.e. non-joinable).
|
||||
thread() : mHandle(0), mNotAThread(true)
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
, mWin32ThreadID(0)
|
||||
, mWin32ThreadID(0)
|
||||
#endif
|
||||
{}
|
||||
{}
|
||||
|
||||
/// Thread starting constructor.
|
||||
/// Construct a @c thread object with a new thread of execution.
|
||||
/// @param[in] aFunction A function pointer to a function of type:
|
||||
/// <tt>void fun(void * arg)</tt>
|
||||
/// @param[in] aArg Argument to the thread function.
|
||||
/// @note This constructor is not fully compatible with the standard C++
|
||||
/// thread class. It is more similar to the pthread_create() (POSIX) and
|
||||
/// CreateThread() (Windows) functions.
|
||||
thread(void (*aFunction)(void *), void * aArg);
|
||||
/// Thread starting constructor.
|
||||
/// Construct a @c thread object with a new thread of execution.
|
||||
/// @param[in] aFunction A function pointer to a function of type:
|
||||
/// <tt>void fun(void * arg)</tt>
|
||||
/// @param[in] aArg Argument to the thread function.
|
||||
/// @note This constructor is not fully compatible with the standard C++
|
||||
/// thread class. It is more similar to the pthread_create() (POSIX) and
|
||||
/// CreateThread() (Windows) functions.
|
||||
thread(void (*aFunction)(void *), void * aArg);
|
||||
|
||||
/// Destructor.
|
||||
/// @note If the thread is joinable upon destruction, @c std::terminate()
|
||||
/// will be called, which terminates the process. It is always wise to do
|
||||
/// @c join() before deleting a thread object.
|
||||
~thread();
|
||||
/// Destructor.
|
||||
/// @note If the thread is joinable upon destruction, @c std::terminate()
|
||||
/// will be called, which terminates the process. It is always wise to do
|
||||
/// @c join() before deleting a thread object.
|
||||
~thread();
|
||||
|
||||
/// Wait for the thread to finish (join execution flows).
|
||||
/// After calling @c join(), the thread object is no longer associated with
|
||||
/// a thread of execution (i.e. it is not joinable, and you may not join
|
||||
/// with it nor detach from it).
|
||||
void join();
|
||||
/// Wait for the thread to finish (join execution flows).
|
||||
/// After calling @c join(), the thread object is no longer associated with
|
||||
/// a thread of execution (i.e. it is not joinable, and you may not join
|
||||
/// with it nor detach from it).
|
||||
void join();
|
||||
|
||||
/// Check if the thread is joinable.
|
||||
/// A thread object is joinable if it has an associated thread of execution.
|
||||
bool joinable() const;
|
||||
/// Check if the thread is joinable.
|
||||
/// A thread object is joinable if it has an associated thread of execution.
|
||||
bool joinable() const;
|
||||
|
||||
/// Detach from the thread.
|
||||
/// After calling @c detach(), the thread object is no longer assicated with
|
||||
/// a thread of execution (i.e. it is not joinable). The thread continues
|
||||
/// execution without the calling thread blocking, and when the thread
|
||||
/// ends execution, any owned resources are released.
|
||||
void detach();
|
||||
/// Detach from the thread.
|
||||
/// After calling @c detach(), the thread object is no longer assicated with
|
||||
/// a thread of execution (i.e. it is not joinable). The thread continues
|
||||
/// execution without the calling thread blocking, and when the thread
|
||||
/// ends execution, any owned resources are released.
|
||||
void detach();
|
||||
|
||||
/// Return the thread ID of a thread object.
|
||||
id get_id() const;
|
||||
/// Return the thread ID of a thread object.
|
||||
id get_id() const;
|
||||
|
||||
/// Get the native handle for this thread.
|
||||
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
|
||||
/// is a @c pthread_t.
|
||||
inline native_handle_type native_handle()
|
||||
{
|
||||
return mHandle;
|
||||
}
|
||||
/// Get the native handle for this thread.
|
||||
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
|
||||
/// is a @c pthread_t.
|
||||
inline native_handle_type native_handle() {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/// Determine the number of threads which can possibly execute concurrently.
|
||||
/// This function is useful for determining the optimal number of threads to
|
||||
/// use for a task.
|
||||
/// @return The number of hardware thread contexts in the system.
|
||||
/// @note If this value is not defined, the function returns zero (0).
|
||||
static unsigned hardware_concurrency();
|
||||
/// Determine the number of threads which can possibly execute concurrently.
|
||||
/// This function is useful for determining the optimal number of threads to
|
||||
/// use for a task.
|
||||
/// @return The number of hardware thread contexts in the system.
|
||||
/// @note If this value is not defined, the function returns zero (0).
|
||||
static unsigned hardware_concurrency();
|
||||
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(thread)
|
||||
_TTHREAD_DISABLE_ASSIGNMENT(thread)
|
||||
|
||||
private:
|
||||
native_handle_type mHandle; ///< Thread handle.
|
||||
mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
|
||||
bool mNotAThread; ///< True if this object is not a thread of execution.
|
||||
void * ti_copy;
|
||||
private:
|
||||
native_handle_type mHandle; ///< Thread handle.
|
||||
mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
|
||||
bool mNotAThread; ///< True if this object is not a thread of execution.
|
||||
void * ti_copy;
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
|
||||
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
|
||||
#endif
|
||||
|
||||
// This is the internal thread wrapper function.
|
||||
// This is the internal thread wrapper function.
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
static unsigned WINAPI wrapper_function(void * aArg);
|
||||
static unsigned WINAPI wrapper_function(void * aArg);
|
||||
#else
|
||||
static void * wrapper_function(void * aArg);
|
||||
static void * wrapper_function(void * aArg);
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
/// Thread ID.
|
||||
/// The thread ID is a unique identifier for each thread.
|
||||
/// @see thread::get_id()
|
||||
class thread::id {
|
||||
public:
|
||||
/// Default constructor.
|
||||
/// The default constructed ID is that of thread without a thread of
|
||||
/// execution.
|
||||
id() : mId(0) {};
|
||||
class thread::id {
|
||||
public:
|
||||
/// Default constructor.
|
||||
/// The default constructed ID is that of thread without a thread of
|
||||
/// execution.
|
||||
id() : mId(0) {};
|
||||
|
||||
id(unsigned long int aId) : mId(aId) {};
|
||||
id(unsigned long int aId) : mId(aId) {};
|
||||
|
||||
id(const id& aId) : mId(aId.mId) {};
|
||||
id(const id & aId) : mId(aId.mId) {};
|
||||
|
||||
inline id & operator=(const id &aId)
|
||||
{
|
||||
mId = aId.mId;
|
||||
return *this;
|
||||
}
|
||||
inline id & operator=(const id & aId) {
|
||||
mId = aId.mId;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline friend bool operator==(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId == aId2.mId);
|
||||
}
|
||||
inline friend bool operator==(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId == aId2.mId);
|
||||
}
|
||||
|
||||
inline friend bool operator!=(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId != aId2.mId);
|
||||
}
|
||||
inline friend bool operator!=(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId != aId2.mId);
|
||||
}
|
||||
|
||||
inline friend bool operator<=(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId <= aId2.mId);
|
||||
}
|
||||
inline friend bool operator<=(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId <= aId2.mId);
|
||||
}
|
||||
|
||||
inline friend bool operator<(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId < aId2.mId);
|
||||
}
|
||||
inline friend bool operator<(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId < aId2.mId);
|
||||
}
|
||||
|
||||
inline friend bool operator>=(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId >= aId2.mId);
|
||||
}
|
||||
inline friend bool operator>=(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId >= aId2.mId);
|
||||
}
|
||||
|
||||
inline friend bool operator>(const id &aId1, const id &aId2)
|
||||
{
|
||||
return (aId1.mId > aId2.mId);
|
||||
}
|
||||
inline friend bool operator>(const id & aId1, const id & aId2) {
|
||||
return (aId1.mId > aId2.mId);
|
||||
}
|
||||
|
||||
inline friend std::ostream& operator <<(std::ostream &os, const id &obj)
|
||||
{
|
||||
os << obj.mId;
|
||||
return os;
|
||||
}
|
||||
inline friend std::ostream & operator <<(std::ostream & os, const id & obj) {
|
||||
os << obj.mId;
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long int mId;
|
||||
};
|
||||
private:
|
||||
unsigned long int mId;
|
||||
};
|
||||
|
||||
|
||||
// Related to <ratio> - minimal to be able to support chrono.
|
||||
typedef long long __intmax_t;
|
||||
typedef long long __intmax_t;
|
||||
|
||||
/// Minimal implementation of the @c ratio class. This class provides enough
|
||||
/// functionality to implement some basic @c chrono classes.
|
||||
template <__intmax_t N, __intmax_t D = 1> class ratio {
|
||||
public:
|
||||
static double _as_double() { return double(N) / double(D); }
|
||||
};
|
||||
|
||||
/// Minimal implementation of the @c chrono namespace.
|
||||
/// The @c chrono namespace provides types for specifying time intervals.
|
||||
namespace chrono {
|
||||
/// Duration template class. This class provides enough functionality to
|
||||
/// implement @c this_thread::sleep_for().
|
||||
template <class _Rep, class _Period = ratio<1> > class duration {
|
||||
private:
|
||||
_Rep rep_;
|
||||
template <__intmax_t N, __intmax_t D = 1> class ratio {
|
||||
public:
|
||||
typedef _Rep rep;
|
||||
typedef _Period period;
|
||||
|
||||
/// Construct a duration object with the given duration.
|
||||
template <class _Rep2>
|
||||
explicit duration(const _Rep2& r) : rep_(r) {};
|
||||
|
||||
/// Return the value of the duration object.
|
||||
rep count() const
|
||||
{
|
||||
return rep_;
|
||||
static double _as_double() {
|
||||
return double(N) / double(D);
|
||||
}
|
||||
};
|
||||
|
||||
// Standard duration types.
|
||||
typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds.
|
||||
typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds.
|
||||
typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds.
|
||||
typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds.
|
||||
typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes.
|
||||
typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours.
|
||||
}
|
||||
/// Minimal implementation of the @c chrono namespace.
|
||||
/// The @c chrono namespace provides types for specifying time intervals.
|
||||
namespace chrono {
|
||||
/// Duration template class. This class provides enough functionality to
|
||||
/// implement @c this_thread::sleep_for().
|
||||
template <class _Rep, class _Period = ratio<1> > class duration {
|
||||
private:
|
||||
_Rep rep_;
|
||||
public:
|
||||
typedef _Rep rep;
|
||||
typedef _Period period;
|
||||
|
||||
/// Construct a duration object with the given duration.
|
||||
template <class _Rep2>
|
||||
explicit duration(const _Rep2 & r) : rep_(r) {};
|
||||
|
||||
/// Return the value of the duration object.
|
||||
rep count() const {
|
||||
return rep_;
|
||||
}
|
||||
};
|
||||
|
||||
// Standard duration types.
|
||||
typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds.
|
||||
typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds.
|
||||
typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds.
|
||||
typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds.
|
||||
typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes.
|
||||
typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours.
|
||||
}
|
||||
|
||||
/// The namespace @c this_thread provides methods for dealing with the
|
||||
/// calling thread.
|
||||
namespace this_thread {
|
||||
/// Return the thread ID of the calling thread.
|
||||
thread::id get_id();
|
||||
namespace this_thread {
|
||||
/// Return the thread ID of the calling thread.
|
||||
thread::id get_id();
|
||||
|
||||
/// Yield execution to another thread.
|
||||
/// Offers the operating system the opportunity to schedule another thread
|
||||
/// that is ready to run on the current processor.
|
||||
inline void yield()
|
||||
{
|
||||
/// Yield execution to another thread.
|
||||
/// Offers the operating system the opportunity to schedule another thread
|
||||
/// that is ready to run on the current processor.
|
||||
inline void yield() {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
Sleep(0);
|
||||
Sleep(0);
|
||||
#else
|
||||
sched_yield();
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// Blocks the calling thread for a period of time.
|
||||
/// @param[in] aTime Minimum time to put the thread to sleep.
|
||||
/// Example usage:
|
||||
/// @code
|
||||
/// // Sleep for 100 milliseconds
|
||||
/// this_thread::sleep_for(chrono::milliseconds(100));
|
||||
/// @endcode
|
||||
/// @note Supported duration types are: nanoseconds, microseconds,
|
||||
/// milliseconds, seconds, minutes and hours.
|
||||
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period>& aTime)
|
||||
{
|
||||
/// Blocks the calling thread for a period of time.
|
||||
/// @param[in] aTime Minimum time to put the thread to sleep.
|
||||
/// Example usage:
|
||||
/// @code
|
||||
/// // Sleep for 100 milliseconds
|
||||
/// this_thread::sleep_for(chrono::milliseconds(100));
|
||||
/// @endcode
|
||||
/// @note Supported duration types are: nanoseconds, microseconds,
|
||||
/// milliseconds, seconds, minutes and hours.
|
||||
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period> & aTime) {
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
|
||||
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
|
||||
#else
|
||||
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
|
||||
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue