diff options
Diffstat (limited to 'src/uscxml/concurrency')
-rw-r--r-- | src/uscxml/concurrency/BlockingQueue.h | 30 | ||||
-rw-r--r-- | src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp | 157 | ||||
-rw-r--r-- | src/uscxml/concurrency/eventqueue/DelayedEventQueue.h | 37 | ||||
-rw-r--r-- | src/uscxml/concurrency/tinythread.cpp | 294 | ||||
-rw-r--r-- | src/uscxml/concurrency/tinythread.h | 773 |
5 files changed, 622 insertions, 669 deletions
diff --git a/src/uscxml/concurrency/BlockingQueue.h b/src/uscxml/concurrency/BlockingQueue.h index 90094bf..16c23d4 100644 --- a/src/uscxml/concurrency/BlockingQueue.h +++ b/src/uscxml/concurrency/BlockingQueue.h @@ -12,26 +12,26 @@ class BlockingQueue { public: BlockingQueue() {} virtual ~BlockingQueue() { - } + } void push(T elem) { - tthread::lock_guard<tthread::mutex> lock(_mutex); - _queue.push_back(elem); - _cond.notify_all(); - } - + tthread::lock_guard<tthread::mutex> lock(_mutex); + _queue.push_back(elem); + _cond.notify_all(); + } + T pop() { - tthread::lock_guard<tthread::mutex> lock(_mutex); - while (_queue.empty()) { - _cond.wait(_mutex); - } - T ret = _queue.front(); - _queue.pop_front(); - return ret; - } + tthread::lock_guard<tthread::mutex> lock(_mutex); + while (_queue.empty()) { + _cond.wait(_mutex); + } + T ret = _queue.front(); + _queue.pop_front(); + return ret; + } tthread::mutex _mutex; - tthread::condition_variable _cond; + tthread::condition_variable _cond; std::list<T> _queue; }; diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp index e2a89b2..e582c13 100644 --- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp +++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp @@ -4,88 +4,89 @@ namespace uscxml { - DelayedEventQueue::DelayedEventQueue() { +DelayedEventQueue::DelayedEventQueue() { #ifndef _WIN32 - evthread_use_pthreads(); + evthread_use_pthreads(); #else - evthread_use_windows_threads(); + evthread_use_windows_threads(); #endif - _eventLoop = event_base_new(); - _thread = NULL; - } + _eventLoop = event_base_new(); + _thread = NULL; +} - DelayedEventQueue::~DelayedEventQueue() { +DelayedEventQueue::~DelayedEventQueue() { // std::cout << "Deleting DelayedEventQueue" << std::endl; - stop(); - if (_thread) - _thread->join(); - if(_eventLoop) - event_base_free(_eventLoop); - } - - void DelayedEventQueue::run(void* instance) { - DelayedEventQueue* THIS = (DelayedEventQueue*)instance; - int result; - while(THIS->_isStarted) { - { - //result = event_base_dispatch(THIS->_eventLoop); - result = event_base_loop(THIS->_eventLoop, EVLOOP_NO_EXIT_ON_EMPTY); - } - } - } - - void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData) { - if(_callbackData.find(eventId) != _callbackData.end()) { - cancelEvent(eventId); - } - - struct timeval delay = {delayMs / 1000, (delayMs % 1000) * 1000}; - struct event* event = event_new(_eventLoop, -1, 0, DelayedEventQueue::timerCallback, &_callbackData[eventId]); - - _callbackData[eventId].eventId = eventId; - _callbackData[eventId].userData = userData; - _callbackData[eventId].eventQueue = this; - _callbackData[eventId].callback = callback; - _callbackData[eventId].event = event; - - event_add(event, &delay); - } - - void DelayedEventQueue::cancelEvent(std::string eventId) { - tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - - if(_callbackData.find(eventId) != _callbackData.end()) { - event_del(_callbackData[eventId].event); - event_free(_callbackData[eventId].event); - _callbackData.erase(eventId); - } - } - - void DelayedEventQueue::start() { - _isStarted = true; - _thread = new tthread::thread(DelayedEventQueue::run, this); - } - - void DelayedEventQueue::stop() { - if (_isStarted) { - _isStarted = false; - event_base_loopbreak(_eventLoop); - _thread->join(); - delete _thread; - } - } - - void DelayedEventQueue::dummyCallback(evutil_socket_t fd, short what, void *arg) { - } - - void DelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg) { - struct callbackData *data = (struct callbackData*)arg; - tthread::lock_guard<tthread::recursive_mutex> lock(data->eventQueue->_mutex); - - std::string eventId = data->eventId; // copy eventId - event_free(data->event); - data->callback(data->userData, eventId); - data->eventQueue->_callbackData.erase(data->eventId); - } + stop(); + if (_thread) + _thread->join(); + if(_eventLoop) + event_base_free(_eventLoop); +} + +void DelayedEventQueue::run(void* instance) { + DelayedEventQueue* THIS = (DelayedEventQueue*)instance; + int result; + while(THIS->_isStarted) { + { + //result = event_base_dispatch(THIS->_eventLoop); + result = event_base_loop(THIS->_eventLoop, EVLOOP_NO_EXIT_ON_EMPTY); + (void)result; + } + } +} + +void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData) { + if(_callbackData.find(eventId) != _callbackData.end()) { + cancelEvent(eventId); + } + + struct timeval delay = {delayMs / 1000, (delayMs % 1000) * 1000}; + struct event* event = event_new(_eventLoop, -1, 0, DelayedEventQueue::timerCallback, &_callbackData[eventId]); + + _callbackData[eventId].eventId = eventId; + _callbackData[eventId].userData = userData; + _callbackData[eventId].eventQueue = this; + _callbackData[eventId].callback = callback; + _callbackData[eventId].event = event; + + event_add(event, &delay); +} + +void DelayedEventQueue::cancelEvent(std::string eventId) { + tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); + + if(_callbackData.find(eventId) != _callbackData.end()) { + event_del(_callbackData[eventId].event); + event_free(_callbackData[eventId].event); + _callbackData.erase(eventId); + } +} + +void DelayedEventQueue::start() { + _isStarted = true; + _thread = new tthread::thread(DelayedEventQueue::run, this); +} + +void DelayedEventQueue::stop() { + if (_isStarted) { + _isStarted = false; + event_base_loopbreak(_eventLoop); + _thread->join(); + delete _thread; + } +} + +void DelayedEventQueue::dummyCallback(evutil_socket_t fd, short what, void *arg) { +} + +void DelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg) { + struct callbackData *data = (struct callbackData*)arg; + tthread::lock_guard<tthread::recursive_mutex> lock(data->eventQueue->_mutex); + + std::string eventId = data->eventId; // copy eventId + event_free(data->event); + data->callback(data->userData, eventId); + data->eventQueue->_callbackData.erase(data->eventId); +} }
\ No newline at end of file diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h index 024e353..8825c27 100644 --- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h +++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h @@ -17,37 +17,36 @@ namespace uscxml { class DelayedEventQueue { public: - - struct callbackData - { - void *userData; - void (*callback)(void*, const std::string eventId); - std::string eventId; - struct event *event; - DelayedEventQueue* eventQueue; - }; + + struct callbackData { + void *userData; + void (*callback)(void*, const std::string eventId); + std::string eventId; + struct event *event; + DelayedEventQueue* eventQueue; + }; DelayedEventQueue(); virtual ~DelayedEventQueue(); - + void addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData); void cancelEvent(std::string eventId); - + void start(); void stop(); static void run(void*); - static void timerCallback(evutil_socket_t fd, short what, void *arg); - static void dummyCallback(evutil_socket_t fd, short what, void *arg); + static void timerCallback(evutil_socket_t fd, short what, void *arg); + static void dummyCallback(evutil_socket_t fd, short what, void *arg); - bool _isStarted; - tthread::thread* _thread; - tthread::recursive_mutex _mutex; - - std::map<std::string, callbackData> _callbackData; + bool _isStarted; + tthread::thread* _thread; + tthread::recursive_mutex _mutex; + + std::map<std::string, callbackData> _callbackData; struct event_base* _eventLoop; }; - + } diff --git a/src/uscxml/concurrency/tinythread.cpp b/src/uscxml/concurrency/tinythread.cpp index 690ecee..c4bab68 100644 --- a/src/uscxml/concurrency/tinythread.cpp +++ b/src/uscxml/concurrency/tinythread.cpp @@ -25,10 +25,10 @@ freely, subject to the following restrictions: #include "tinythread.h" #if defined(_TTHREAD_POSIX_) - #include <unistd.h> - #include <map> +#include <unistd.h> +#include <map> #elif defined(_TTHREAD_WIN32_) - #include <process.h> +#include <process.h> #endif @@ -49,73 +49,68 @@ namespace tthread { //------------------------------------------------------------------------------ #if defined(_TTHREAD_WIN32_) - #define _CONDITION_EVENT_ONE 0 - #define _CONDITION_EVENT_ALL 1 +#define _CONDITION_EVENT_ONE 0 +#define _CONDITION_EVENT_ALL 1 #endif #if defined(_TTHREAD_WIN32_) -condition_variable::condition_variable() : mWaitersCount(0) -{ - mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL); - mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL); - InitializeCriticalSection(&mWaitersCountLock); +condition_variable::condition_variable() : mWaitersCount(0) { + mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL); + mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSection(&mWaitersCountLock); } #endif #if defined(_TTHREAD_WIN32_) -condition_variable::~condition_variable() -{ - CloseHandle(mEvents[_CONDITION_EVENT_ONE]); - CloseHandle(mEvents[_CONDITION_EVENT_ALL]); - DeleteCriticalSection(&mWaitersCountLock); +condition_variable::~condition_variable() { + CloseHandle(mEvents[_CONDITION_EVENT_ONE]); + CloseHandle(mEvents[_CONDITION_EVENT_ALL]); + DeleteCriticalSection(&mWaitersCountLock); } #endif #if defined(_TTHREAD_WIN32_) -void condition_variable::_wait() -{ - // Wait for either event to become signaled due to notify_one() or - // notify_all() being called - int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE); - - // Check if we are the last waiter - EnterCriticalSection(&mWaitersCountLock); - -- mWaitersCount; - bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && - (mWaitersCount == 0); - LeaveCriticalSection(&mWaitersCountLock); - - // If we are the last waiter to be notified to stop waiting, reset the event - if(lastWaiter) - ResetEvent(mEvents[_CONDITION_EVENT_ALL]); +void condition_variable::_wait() { + // Wait for either event to become signaled due to notify_one() or + // notify_all() being called + int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE); + + // Check if we are the last waiter + EnterCriticalSection(&mWaitersCountLock); + -- mWaitersCount; + bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && + (mWaitersCount == 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we are the last waiter to be notified to stop waiting, reset the event + if(lastWaiter) + ResetEvent(mEvents[_CONDITION_EVENT_ALL]); } #endif #if defined(_TTHREAD_WIN32_) -void condition_variable::notify_one() -{ - // Are there any waiters? - EnterCriticalSection(&mWaitersCountLock); - bool haveWaiters = (mWaitersCount > 0); - LeaveCriticalSection(&mWaitersCountLock); - - // If we have any waiting threads, send them a signal - if(haveWaiters) - SetEvent(mEvents[_CONDITION_EVENT_ONE]); +void condition_variable::notify_one() { + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ONE]); } #endif #if defined(_TTHREAD_WIN32_) -void condition_variable::notify_all() -{ - // Are there any waiters? - EnterCriticalSection(&mWaitersCountLock); - bool haveWaiters = (mWaitersCount > 0); - LeaveCriticalSection(&mWaitersCountLock); - - // If we have any waiting threads, send them a signal - if(haveWaiters) - SetEvent(mEvents[_CONDITION_EVENT_ALL]); +void condition_variable::notify_all() { + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ALL]); } #endif @@ -128,16 +123,15 @@ void condition_variable::notify_all() //------------------------------------------------------------------------------ #if defined(_TTHREAD_POSIX_) -static thread::id _pthread_t_to_ID(const pthread_t &aHandle) -{ - static mutex idMapLock; - static std::map<pthread_t, unsigned long int> idMap; - static unsigned long int idCount(1); - - lock_guard<mutex> guard(idMapLock); - if(idMap.find(aHandle) == idMap.end()) - idMap[aHandle] = idCount ++; - return thread::id(idMap[aHandle]); +static thread::id _pthread_t_to_ID(const pthread_t &aHandle) { + static mutex idMapLock; + static std::map<pthread_t, unsigned long int> idMap; + static unsigned long int idCount(1); + + lock_guard<mutex> guard(idMapLock); + if(idMap.find(aHandle) == idMap.end()) + idMap[aHandle] = idCount ++; + return thread::id(idMap[aHandle]); } #endif // _TTHREAD_POSIX_ @@ -148,9 +142,9 @@ static thread::id _pthread_t_to_ID(const pthread_t &aHandle) /// Information to pass to the new thread (what to run). struct _thread_start_info { - void (*mFunction)(void *); ///< Pointer to the function to be executed. - void * mArg; ///< Function argument for the thread function. - thread * mThread; ///< Pointer to the thread object. + void (*mFunction)(void *); ///< Pointer to the function to be executed. + void * mArg; ///< Function argument for the thread function. + thread * mThread; ///< Pointer to the thread object. }; // Thread wrapper function. @@ -160,129 +154,116 @@ unsigned WINAPI thread::wrapper_function(void * aArg) void * thread::wrapper_function(void * aArg) #endif { - // Get thread startup information - _thread_start_info * ti = (_thread_start_info *) aArg; - - try - { - // Call the actual client thread function - ti->mFunction(ti->mArg); - } - catch(...) - { - // Uncaught exceptions will terminate the application (default behavior - // according to C++11) - std::terminate(); - } - - // The thread is no longer executing - lock_guard<mutex> guard(ti->mThread->mDataMutex); - ti->mThread->mNotAThread = true; - - // The thread is responsible for freeing the startup information - delete ti; - - return 0; + // Get thread startup information + _thread_start_info * ti = (_thread_start_info *) aArg; + + try { + // Call the actual client thread function + ti->mFunction(ti->mArg); + } catch(...) { + // Uncaught exceptions will terminate the application (default behavior + // according to C++11) + std::terminate(); + } + + // The thread is no longer executing + lock_guard<mutex> guard(ti->mThread->mDataMutex); + ti->mThread->mNotAThread = true; + + // The thread is responsible for freeing the startup information + delete ti; + + return 0; } -thread::thread(void (*aFunction)(void *), void * aArg) -{ - // Serialize access to this thread structure - lock_guard<mutex> guard(mDataMutex); +thread::thread(void (*aFunction)(void *), void * aArg) { + // Serialize access to this thread structure + lock_guard<mutex> guard(mDataMutex); - // Fill out the thread startup information (passed to the thread wrapper, - // which will eventually free it) - _thread_start_info * ti = new _thread_start_info; - ti->mFunction = aFunction; - ti->mArg = aArg; - ti->mThread = this; + // Fill out the thread startup information (passed to the thread wrapper, + // which will eventually free it) + _thread_start_info * ti = new _thread_start_info; + ti->mFunction = aFunction; + ti->mArg = aArg; + ti->mThread = this; - // The thread is now alive - mNotAThread = false; + // The thread is now alive + mNotAThread = false; - // Create the thread + // Create the thread #if defined(_TTHREAD_WIN32_) - mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID); + mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID); #elif defined(_TTHREAD_POSIX_) - if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0) - mHandle = 0; + if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0) + mHandle = 0; #endif - // Did we fail to create the thread? - if(!mHandle) - { - mNotAThread = true; - delete ti; - } + // Did we fail to create the thread? + if(!mHandle) { + mNotAThread = true; + delete ti; + } } -thread::~thread() -{ - if(joinable()) - std::terminate(); +thread::~thread() { + if(joinable()) + std::terminate(); } -void thread::join() -{ - if(joinable()) - { +void thread::join() { + if(joinable()) { #if defined(_TTHREAD_WIN32_) - WaitForSingleObject(mHandle, INFINITE); - CloseHandle(mHandle); + WaitForSingleObject(mHandle, INFINITE); + CloseHandle(mHandle); #elif defined(_TTHREAD_POSIX_) - pthread_join(mHandle, NULL); + pthread_join(mHandle, NULL); #endif - } + } } -bool thread::joinable() const -{ - mDataMutex.lock(); - bool result = !mNotAThread; - mDataMutex.unlock(); - return result; +bool thread::joinable() const { + mDataMutex.lock(); + bool result = !mNotAThread; + mDataMutex.unlock(); + return result; } -void thread::detach() -{ - mDataMutex.lock(); - if(!mNotAThread) - { +void thread::detach() { + mDataMutex.lock(); + if(!mNotAThread) { #if defined(_TTHREAD_WIN32_) - CloseHandle(mHandle); + CloseHandle(mHandle); #elif defined(_TTHREAD_POSIX_) - pthread_detach(mHandle); + pthread_detach(mHandle); #endif - mNotAThread = true; - } - mDataMutex.unlock(); + mNotAThread = true; + } + mDataMutex.unlock(); } -thread::id thread::get_id() const -{ - if(!joinable()) - return id(); +thread::id thread::get_id() const { + if(!joinable()) + return id(); #if defined(_TTHREAD_WIN32_) - return id((unsigned long int) mWin32ThreadID); + return id((unsigned long int) mWin32ThreadID); #elif defined(_TTHREAD_POSIX_) - return _pthread_t_to_ID(mHandle); + return _pthread_t_to_ID(mHandle); #endif } -unsigned thread::hardware_concurrency() -{ +unsigned thread::hardware_concurrency() { #if defined(_TTHREAD_WIN32_) - SYSTEM_INFO si; - GetSystemInfo(&si); - return (int) si.dwNumberOfProcessors; + SYSTEM_INFO si; + GetSystemInfo(&si); + return (int) si.dwNumberOfProcessors; #elif defined(_SC_NPROCESSORS_ONLN) - return (int) sysconf(_SC_NPROCESSORS_ONLN); + return (int) sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_SC_NPROC_ONLN) - return (int) sysconf(_SC_NPROC_ONLN); + return (int) sysconf(_SC_NPROC_ONLN); #else - // The standard requires this function to return zero if the number of - // hardware cores could not be determined. - return 0; + // The standard requires this function to return zero if the number of + // hardware cores could not be determined. + return 0; #endif } @@ -291,12 +272,11 @@ unsigned thread::hardware_concurrency() // this_thread //------------------------------------------------------------------------------ -thread::id this_thread::get_id() -{ +thread::id this_thread::get_id() { #if defined(_TTHREAD_WIN32_) - return thread::id((unsigned long int) GetCurrentThreadId()); + return thread::id((unsigned long int) GetCurrentThreadId()); #elif defined(_TTHREAD_POSIX_) - return _pthread_t_to_ID(pthread_self()); + return _pthread_t_to_ID(pthread_self()); #endif } diff --git a/src/uscxml/concurrency/tinythread.h b/src/uscxml/concurrency/tinythread.h index aed7b58..2e5caa0 100644 --- a/src/uscxml/concurrency/tinythread.h +++ b/src/uscxml/concurrency/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,21 +95,21 @@ 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) \ +#define _TTHREAD_DISABLE_ASSIGNMENT(name) \ name(const name&) = delete; \ name& operator=(const name&) = delete; #else - #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ +#define _TTHREAD_DISABLE_ASSIGNMENT(name) \ name(const name&); \ name& operator=(const name&); #endif @@ -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 @@ -157,89 +157,84 @@ namespace tthread { /// on that object). /// @see recursive_mutex class mutex { - public: - /// Constructor. - mutex() +public: + /// Constructor. + mutex() #if defined(_TTHREAD_WIN32_) - : mAlreadyLocked(false) + : mAlreadyLocked(false) #endif - { + { #if defined(_TTHREAD_WIN32_) - InitializeCriticalSection(&mHandle); + InitializeCriticalSection(&mHandle); #else - pthread_mutex_init(&mHandle, NULL); + pthread_mutex_init(&mHandle, NULL); #endif - } + } - /// Destructor. - ~mutex() - { + /// Destructor. + ~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); - while(mAlreadyLocked) Sleep(1000); // Simulate deadlock... - mAlreadyLocked = true; + EnterCriticalSection(&mHandle); + while(mAlreadyLocked) Sleep(1000); // Simulate deadlock... + mAlreadyLocked = true; #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_) - bool ret = (TryEnterCriticalSection(&mHandle) ? true : false); - if(ret && mAlreadyLocked) - { - LeaveCriticalSection(&mHandle); - ret = false; - } - return ret; + bool ret = (TryEnterCriticalSection(&mHandle) ? true : false); + if(ret && mAlreadyLocked) { + LeaveCriticalSection(&mHandle); + ret = false; + } + return ret; #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_) - mAlreadyLocked = false; - LeaveCriticalSection(&mHandle); + mAlreadyLocked = false; + LeaveCriticalSection(&mHandle); #else - pthread_mutex_unlock(&mHandle); + pthread_mutex_unlock(&mHandle); #endif - } + } - _TTHREAD_DISABLE_ASSIGNMENT(mutex) + _TTHREAD_DISABLE_ASSIGNMENT(mutex) - private: +private: #if defined(_TTHREAD_WIN32_) - CRITICAL_SECTION mHandle; - bool mAlreadyLocked; + CRITICAL_SECTION mHandle; + bool mAlreadyLocked; #else - pthread_mutex_t mHandle; + pthread_mutex_t mHandle; #endif - friend class condition_variable; + friend class condition_variable; }; /// Recursive mutex class. @@ -249,79 +244,74 @@ class mutex { /// number of times). /// @see mutex class recursive_mutex { - public: - /// Constructor. - 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. @@ -341,27 +331,25 @@ class recursive_mutex { template <class T> class lock_guard { - public: - typedef T mutex_type; - - lock_guard() : mMutex(0) {} - - /// 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(); - } - - private: - mutex_type * mMutex; +public: + typedef T mutex_type; + + lock_guard() : mMutex(0) {} + + /// 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(); + } + +private: + mutex_type * mMutex; }; /// Condition variable class. @@ -390,179 +378,173 @@ class lock_guard { /// } /// @endcode class condition_variable { - public: - /// Constructor. +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); - } -#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) - { + ~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) { #if defined(_TTHREAD_WIN32_) - // 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(); + // 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(); #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: +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) -#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); - - /// 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(); - - /// 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(); - - /// 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; - } - - /// 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) - - 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. + , 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); + + /// 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(); + + /// 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(); + + /// 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; + } + + /// 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) + +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. #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 }; @@ -570,60 +552,52 @@ class thread { /// 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) {}; - - id(unsigned long int aId) : mId(aId) {}; - - id(const id& aId) : mId(aId.mId) {}; - - 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 std::ostream& operator <<(std::ostream &os, const id &obj) - { - os << obj.mId; - return os; - } - - private: - unsigned long int mId; +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(const id& aId) : mId(aId.mId) {}; + + 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 std::ostream& operator <<(std::ostream &os, const id &obj) { + os << obj.mId; + return os; + } + +private: + unsigned long int mId; }; @@ -633,77 +607,76 @@ 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); } +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_; - 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. +/// 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(); - - /// 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() - { +/// 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() { #if defined(_TTHREAD_WIN32_) - Sleep(0); + Sleep(0); #else - 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) - { + 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) { #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 - } +} } } |