summaryrefslogtreecommitdiffstats
path: root/src/uscxml/concurrency
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/concurrency')
-rw-r--r--src/uscxml/concurrency/BlockingQueue.h79
-rw-r--r--src/uscxml/concurrency/DelayedEventQueue.cpp166
-rw-r--r--src/uscxml/concurrency/DelayedEventQueue.h86
-rw-r--r--src/uscxml/concurrency/EventBase.cpp74
-rw-r--r--src/uscxml/concurrency/EventBase.h61
-rw-r--r--src/uscxml/concurrency/Timer.cpp115
-rw-r--r--src/uscxml/concurrency/Timer.h74
-rw-r--r--src/uscxml/concurrency/tinythread.cpp335
-rw-r--r--src/uscxml/concurrency/tinythread.h726
9 files changed, 0 insertions, 1716 deletions
diff --git a/src/uscxml/concurrency/BlockingQueue.h b/src/uscxml/concurrency/BlockingQueue.h
deleted file mode 100644
index e53de25..0000000
--- a/src/uscxml/concurrency/BlockingQueue.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file
- * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#ifndef BLOCKINGQUEUE_H_4LEVMY0N
-#define BLOCKINGQUEUE_H_4LEVMY0N
-
-#include "uscxml/Common.h"
-#include "uscxml/concurrency/tinythread.h"
-#include <list>
-
-namespace uscxml {
-namespace concurrency {
-
-template <class T>
-class BlockingQueue {
-public:
- BlockingQueue() {}
- virtual ~BlockingQueue() {
- }
-
- virtual void push(const T& elem) {
- tthread::lock_guard<tthread::mutex> lock(_mutex);
- _queue.push_back(elem);
- _cond.notify_all();
- }
-
- virtual void push_front(const T& elem) {
- tthread::lock_guard<tthread::mutex> lock(_mutex);
- _queue.push_front(elem);
- _cond.notify_all();
- }
-
- virtual T pop() {
- tthread::lock_guard<tthread::mutex> lock(_mutex);
-// std::cout << "Popping from " << this << std::endl;
- while (_queue.empty()) {
- _cond.wait(_mutex);
- }
- T ret = _queue.front();
- _queue.pop_front();
- return ret;
- }
-
- virtual void clear() {
- tthread::lock_guard<tthread::mutex> lock(_mutex);
- _queue.clear();
- }
-
- virtual bool isEmpty() {
- tthread::lock_guard<tthread::mutex> lock(_mutex);
- return _queue.empty();
- }
-
-protected:
- tthread::mutex _mutex;
- tthread::condition_variable _cond;
- std::list<T> _queue;
-};
-
-}
-}
-
-#endif /* end of include guard: BLOCKINGQUEUE_H_4LEVMY0N */
diff --git a/src/uscxml/concurrency/DelayedEventQueue.cpp b/src/uscxml/concurrency/DelayedEventQueue.cpp
deleted file mode 100644
index 897e99d..0000000
--- a/src/uscxml/concurrency/DelayedEventQueue.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * @file
- * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#include "DelayedEventQueue.h"
-#include "uscxml/messages/Event.h"
-
-#include <glog/logging.h>
-
-#include <event2/event.h>
-#include "event2/thread.h"
-
-namespace uscxml {
-
-DelayedEventQueue::DelayedEventQueue() {
-#ifndef _WIN32
- evthread_use_pthreads();
-#else
- evthread_use_windows_threads();
-#endif
- _eventLoop = event_base_new();
- _thread = NULL;
- _isStarted = false;
-}
-
-DelayedEventQueue::~DelayedEventQueue() {
-// std::cout << "Deleting DelayedEventQueue" << std::endl;
- stop();
- if (_thread && _isStarted)
- _thread->join();
- if(_eventLoop)
- event_base_free(_eventLoop);
-}
-
-void DelayedEventQueue::run(void* instance) {
- DelayedEventQueue* INSTANCE = (DelayedEventQueue*)instance;
- int result;
- while(INSTANCE->_isStarted) {
-// #ifndef EVLOOP_NO_EXIT_ON_EMPTY
-// result = event_base_dispatch(INSTANCE->_eventLoop);
-// #else
- result = event_base_loop(INSTANCE->_eventLoop, EVLOOP_NO_EXIT_ON_EMPTY);
-//#endif
- (void)result;
- }
-}
-
-void DelayedEventQueue::addEvent(std::string eventId, int fd, short opMask, void (*callback)(void*, const std::string eventId), void* userData, bool persist) {
- if(_callbackData.find(eventId) != _callbackData.end()) {
- cancelEvent(eventId);
- }
-
- if (persist)
- opMask |= EV_PERSIST;
-
- struct event* event = event_new(_eventLoop, fd, opMask, DelayedEventQueue::fileCallback, &_callbackData[eventId]);
-
- _callbackData[eventId].eventId = eventId;
- _callbackData[eventId].userData = userData;
- _callbackData[eventId].eventQueue = this;
- _callbackData[eventId].callback = callback;
- _callbackData[eventId].event = event;
- _callbackData[eventId].persist = false;
-
- event_add(event, NULL);
-
-}
-
-void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist) {
- if(_callbackData.find(eventId) != _callbackData.end()) {
- cancelEvent(eventId);
- }
-
- struct timeval delay = {delayMs / 1000, (delayMs % 1000) * 1000};
- struct event* event = event_new(_eventLoop, -1, (persist ? EV_PERSIST : 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;
- _callbackData[eventId].persist = persist;
-
- event_add(event, &delay);
-}
-
-void DelayedEventQueue::cancelAllEvents() {
- tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
- while(_callbackData.size() > 0) {
- event_del(_callbackData[_callbackData.begin()->first].event);
- event_free(_callbackData[_callbackData.begin()->first].event);
- _callbackData.erase(_callbackData.begin());
- }
-}
-
-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);
- }
- if (_thread) {
- _thread->join();
- delete _thread;
- _thread = NULL;
- }
-}
-
-void DelayedEventQueue::dummyCallback(evutil_socket_t fd, short what, void *arg) {
-}
-
-void DelayedEventQueue::fileCallback(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
- data->callback(data->userData, eventId);
-}
-
-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
- try {
- data->callback(data->userData, eventId);
- } catch (Event e) {
- LOG(ERROR) << "Exception thrown when executing delayed event:" << std::endl << e << std::endl;
- } catch (...) {
- LOG(ERROR) << "Exception thrown when executing delayed event" << std::endl;
- }
- if (!data->persist) {
- event_free(data->event);
- data->eventQueue->_callbackData.erase(data->eventId);
- }
-}
-
-} \ No newline at end of file
diff --git a/src/uscxml/concurrency/DelayedEventQueue.h b/src/uscxml/concurrency/DelayedEventQueue.h
deleted file mode 100644
index 7c2789f..0000000
--- a/src/uscxml/concurrency/DelayedEventQueue.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @file
- * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#ifndef DELAYEDEVENTQUEUE_H_JA6WRBVP
-#define DELAYEDEVENTQUEUE_H_JA6WRBVP
-
-#include "uscxml/concurrency/tinythread.h"
-
-
-#include "uscxml/Common.h"
-#include "event2/util.h" // for evutil_socket_t
-#include <event2/event.h>
-
-#include <inttypes.h>
-
-#include <map>
-#include <string>
-
-namespace uscxml {
-
-class USCXML_API DelayedEventQueue {
-public:
-
- enum OpMask {
- DEQ_READ = EV_READ,
- DEQ_WRITE = EV_WRITE,
- DEQ_SIGNAL = EV_SIGNAL
- };
-
- struct callbackData {
- void *userData;
- void (*callback)(void*, const std::string eventId);
- std::string eventId;
- bool persist;
- struct event *event;
- DelayedEventQueue* eventQueue;
- };
-
- DelayedEventQueue();
- virtual ~DelayedEventQueue();
-
- void addEvent(std::string eventId, int fd, short opMask, void (*callback)(void*, const std::string eventId), void* userData, bool persist = true);
- void addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist = false);
- void cancelEvent(std::string eventId);
- void cancelAllEvents();
-
- void start();
- void stop();
- static void run(void*);
-
- bool isEmpty() {
- return _callbackData.empty();
- }
-
- static void timerCallback(evutil_socket_t fd, short what, void *arg);
- static void fileCallback(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;
- struct event_base* _eventLoop;
-};
-
-}
-
-
-#endif /* end of include guard: DELAYEDEVENTQUEUE_H_JA6WRBVP */
diff --git a/src/uscxml/concurrency/EventBase.cpp b/src/uscxml/concurrency/EventBase.cpp
deleted file mode 100644
index ec25181..0000000
--- a/src/uscxml/concurrency/EventBase.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @file
- * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#include "EventBase.h"
-
-namespace uscxml {
-
-std::map<std::string, boost::weak_ptr<EventBase> > EventBase::_eventBases;
-tthread::recursive_mutex EventBase::_instanceMutex;
-
-boost::shared_ptr<EventBase> EventBase::get(const std::string& name) {
- tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex);
-
- std::map<std::string, boost::weak_ptr<EventBase> >::iterator instIter = _eventBases.begin();
- while(instIter != _eventBases.end()) {
- if (!instIter->second.lock()) {
- _eventBases.erase(instIter++);
- } else {
- instIter++;
- }
- }
-
- instIter = _eventBases.find(name);
- boost::shared_ptr<EventBase> instance = instIter->second.lock();
- if (instance)
- return instance;
-
- instance = boost::shared_ptr<EventBase>(new EventBase());
- _eventBases.insert(std::make_pair(name, instance));
-
- return instance;
-}
-
-EventBase::EventBase() {
- base = event_base_new();
- _isStarted = true;
- _thread = new tthread::thread(EventBase::run, this);
-}
-
-void EventBase::run(void* arg) {
- EventBase* INSTANCE = (EventBase*)arg;
- int result;
-
- while(INSTANCE->_isStarted) {
- result = event_base_loop(INSTANCE->base, EVLOOP_NO_EXIT_ON_EMPTY);
- (void)result;
- }
-}
-
-EventBase::~EventBase() {
- _isStarted = false;
- event_base_loopbreak(base);
- _thread->join();
- event_base_free(base);
- delete _thread;
-}
-
-} \ No newline at end of file
diff --git a/src/uscxml/concurrency/EventBase.h b/src/uscxml/concurrency/EventBase.h
deleted file mode 100644
index 22bd664..0000000
--- a/src/uscxml/concurrency/EventBase.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file
- * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#ifndef EVENTBASE_H_C479DA74
-#define EVENTBASE_H_C479DA74
-
-#include "uscxml/Common.h"
-#include "uscxml/concurrency/tinythread.h"
-
-extern "C" {
-#include <event2/event.h>
-#include <event2/buffer.h>
-#include <event2/bufferevent.h>
-}
-
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-#include <map>
-#include <string>
-
-namespace uscxml {
-
-class USCXML_API EventBase {
-public:
- EventBase();
- virtual ~EventBase();
-
- static boost::shared_ptr<EventBase> get(const std::string& name);
- struct event_base* base;
-
-protected:
-
- static void run(void*);
-
- tthread::thread* _thread;
- bool _isStarted;
-
- static std::map<std::string, boost::weak_ptr<EventBase> > _eventBases;
- static tthread::recursive_mutex _instanceMutex;
-
-};
-
-}
-
-#endif /* end of include guard: EVENTBASE_H_C479DA74 */
diff --git a/src/uscxml/concurrency/Timer.cpp b/src/uscxml/concurrency/Timer.cpp
deleted file mode 100644
index 77b712f..0000000
--- a/src/uscxml/concurrency/Timer.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2013 Alex Reece.
-//
-// A cross platform monotonic timer.
-
-// see https://github.com/awreece/monotonic_timer
-
-#include "uscxml/config.h"
-#ifdef HAS_UNISTD_H
-#include <unistd.h>
-#endif
-#include "Timer.h"
-
-#define NANOS_PER_SECF 1000000000.0
-#define USECS_PER_SEC 1000000
-
-#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
-// If we have it, use clock_gettime and CLOCK_MONOTONIC.
-
-#include <time.h>
-
-double uscxml::Timer::monotonic_seconds() {
- struct timespec time;
- // Note: Make sure to link with -lrt to define clock_gettime.
- clock_gettime(CLOCK_MONOTONIC, &time);
- return ((double) time.tv_sec) + ((double) time.tv_nsec / (NANOS_PER_SECF));
-}
-
-#elif defined(__APPLE__)
-// If we don't have CLOCK_MONOTONIC, we might be on a Mac. There we instead
-// use mach_absolute_time().
-
-#include <mach/mach_time.h>
-
-static mach_timebase_info_data_t info;
-static void __attribute__((constructor)) init_info() {
- mach_timebase_info(&info);
-}
-
-double uscxml::Timer::monotonic_seconds() {
- uint64_t time = mach_absolute_time();
- double dtime = (double) time;
- dtime *= (double) info.numer;
- dtime /= (double) info.denom;
- return dtime / NANOS_PER_SECF;
-}
-
-#elif defined(_MSC_VER)
-// On Windows, use QueryPerformanceCounter and QueryPerformanceFrequency.
-
-#define NOMINMAX
-#include <windows.h>
-
-static double PCFreq = 0.0;
-__int64 CounterStart = 0;
-
-double uscxml::Timer::monotonic_seconds() {
- if (CounterStart == 0) {
- // Accoring to http://stackoverflow.com/a/1739265/447288, this will
- // properly initialize the QueryPerformanceCounter.
-
- LARGE_INTEGER li;
- int has_qpc = QueryPerformanceFrequency(&li);
-
- PCFreq = ((double) li.QuadPart) / 1000.0;
- }
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- return double(li.QuadPart - CounterStart)/PCFreq;
-}
-
-#else
-// Fall back to rdtsc. The reason we don't use clock() is this scary message
-// from the man page:
-// "On several other implementations, the value returned by clock() also
-// includes the times of any children whose status has been collected via
-// wait(2) (or another wait-type call)."
-//
-// Also, clock() only has microsecond accuracy.
-//
-// This whitepaper offered excellent advice on how to use rdtscp for
-// profiling: http://download.intel.com/embedded/software/IA/324264.pdf
-//
-// Unfortunately, we can't follow its advice exactly with our semantics,
-// so we're just going to use rdtscp with cpuid.
-//
-// Note that rdtscp will only be available on new processors.
-
-#include <stdint.h>
-
-static inline uint64_t rdtsc() {
- uint32_t hi, lo;
- asm volatile("rdtscp\n"
- "movl %%edx, %0\n"
- "movl %%eax, %1\n"
- "cpuid"
- : "=r" (hi), "=r" (lo) : : "%rax", "%rbx", "%rcx", "%rdx");
- return (((uint64_t)hi) << 32) | (uint64_t)lo;
-}
-
-static uint64_t rdtsc_per_sec = 0;
-static void __attribute__((constructor)) init_rdtsc_per_sec() {
- uint64_t before, after;
-
- before = rdtsc();
- usleep(USECS_PER_SEC);
- after = rdtsc();
-
- rdtsc_per_sec = after - before;
-}
-
-double uscxml::Timer::monotonic_seconds() {
- return (double) rdtsc() / (double) rdtsc_per_sec;
-}
-
-#endif
diff --git a/src/uscxml/concurrency/Timer.h b/src/uscxml/concurrency/Timer.h
deleted file mode 100644
index 1ecfeb2..0000000
--- a/src/uscxml/concurrency/Timer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2013 Alex Reece.
-//
-// A cross platform monotonic timer.
-
-// see https://github.com/awreece/monotonic_timer
-
-#ifndef MONOTONIC_TIMER_H_
-#define MONOTONIC_TIMER_H_
-
-#include "uscxml/Common.h"
-
-// Returns seconds since some unspecified start time (guaranteed to be
-// monotonicly increasing).
-
-// Copyright 2015 Stefan Radomski.
-
-namespace uscxml {
-
-class USCXML_API Timer {
-public:
-
- static double monotonic_seconds();
-
- Timer() {
- invocations = 0;
- elapsed = 0;
- }
-
- void start() {
- if (invocations == 0) {
- started = monotonic_seconds();
- }
- invocations++;
- }
-
- void reset() {
- elapsed = 0;
- }
-
- void stop() {
- if (invocations == 0)
- return;
-
- invocations--;
- if (invocations == 0) {
- elapsed += monotonic_seconds() - started;
- }
- }
-
- ~Timer() {
- }
- double elapsed;
-
-protected:
- size_t invocations;
- double started;
-};
-
-class USCXML_API Measurement {
-public:
- Measurement(Timer* timer) : timer(timer) {
- timer->start();
- }
-
- ~Measurement() {
- timer->stop();
- }
-
-protected:
- Timer* timer;
-};
-
-}
-#endif // MONOTONIC_TIMER_H_
diff --git a/src/uscxml/concurrency/tinythread.cpp b/src/uscxml/concurrency/tinythread.cpp
deleted file mode 100644
index d46cda3..0000000
--- a/src/uscxml/concurrency/tinythread.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
-Copyright (c) 2010-2012 Marcus Geelnard
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software. This version was altered!
-
- 3. This notice may not be removed or altered from any source
- distribution.
-*/
-
-#include <exception>
-#include "tinythread.h"
-
-#if defined(_TTHREAD_POSIX_)
-#include <unistd.h>
-#include <map>
-#elif defined(_TTHREAD_WIN32_)
-#include <process.h>
-#endif
-
-namespace tthread {
-
-unsigned long long int timeStamp() {
- unsigned long long int time = 0;
-#ifdef WIN32
- FILETIME tv;
- GetSystemTimeAsFileTime(&tv);
- time = (((unsigned long long int) tv.dwHighDateTime) << 32) + tv.dwLowDateTime;
- time /= 10000;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- time += tv.tv_sec * 1000;
- time += tv.tv_usec / 1000;
-#endif
- return time;
-}
-
-//------------------------------------------------------------------------------
-// condition_variable
-//------------------------------------------------------------------------------
-// NOTE 1: The Win32 implementation of the condition_variable class is based on
-// the corresponding implementation in GLFW, which in turn is based on a
-// description by Douglas C. Schmidt and Irfan Pyarali:
-// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
-//
-// NOTE 2: Windows Vista actually has native support for condition variables
-// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to
-// be portable with pre-Vista Windows versions, so TinyThread++ does not use
-// Vista condition variables.
-//------------------------------------------------------------------------------
-
-#if defined(_TTHREAD_WIN32_)
-#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);
-}
-#endif
-
-#if defined(_TTHREAD_WIN32_)
-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(unsigned int ms) {
- if (ms <= 0)
- ms = INFINITE;
- // Wait for either event to become signaled due to notify_one() or
- // notify_all() being called
- int result = WaitForMultipleObjects(2, mEvents, FALSE, ms);
- if (result == WAIT_FAILED) {
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL);
-// UM_LOG_ERR("%s", lpMsgBuf);
- LocalFree(lpMsgBuf);
-
- }
-
- // 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]);
-}
-#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]);
-}
-#endif
-
-
-//------------------------------------------------------------------------------
-// POSIX pthread_t to unique thread::id mapping logic.
-// Note: Here we use a global thread safe std::map to convert instances of
-// pthread_t to small thread identifier numbers (unique within one process).
-// This method should be portable across different POSIX implementations.
-//------------------------------------------------------------------------------
-
-#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]);
-}
-#endif // _TTHREAD_POSIX_
-
-
-//------------------------------------------------------------------------------
-// thread
-//------------------------------------------------------------------------------
-
-/// 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.
-};
-
-// Thread wrapper function.
-#if defined(_TTHREAD_WIN32_)
-unsigned WINAPI thread::wrapper_function(void * aArg)
-#elif defined(_TTHREAD_POSIX_)
-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;
-}
-
-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;
-
- // The thread is now alive
- mNotAThread = false;
-
- // Create the thread
-#if defined(_TTHREAD_WIN32_)
- 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;
-#endif
-
- // Did we fail to create the thread?
- if(!mHandle) {
- mNotAThread = true;
- delete ti;
- }
-}
-
-thread::~thread() {
- if(joinable())
- std::terminate();
-}
-
-void thread::join() {
- if(joinable()) {
-#if defined(_TTHREAD_WIN32_)
- WaitForSingleObject(mHandle, INFINITE);
- CloseHandle(mHandle);
-#elif defined(_TTHREAD_POSIX_)
- pthread_join(mHandle, NULL);
-#endif
- }
-}
-
-bool thread::joinable() const {
- mDataMutex.lock();
- bool result = !mNotAThread;
- mDataMutex.unlock();
- return result;
-}
-
-void thread::detach() {
- mDataMutex.lock();
- if(!mNotAThread) {
-#if defined(_TTHREAD_WIN32_)
- CloseHandle(mHandle);
-#elif defined(_TTHREAD_POSIX_)
- pthread_detach(mHandle);
-#endif
- mNotAThread = true;
- }
- mDataMutex.unlock();
-}
-
-thread::id thread::get_id() const {
- if(!joinable())
- return id();
-#if defined(_TTHREAD_WIN32_)
- return id((unsigned long int) mWin32ThreadID);
-#elif defined(_TTHREAD_POSIX_)
- return _pthread_t_to_ID(mHandle);
-#endif
-}
-
-unsigned thread::hardware_concurrency() {
-#if defined(_TTHREAD_WIN32_)
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- return (int) si.dwNumberOfProcessors;
-#elif defined(_SC_NPROCESSORS_ONLN)
- return (int) sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(_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;
-#endif
-}
-
-
-//------------------------------------------------------------------------------
-// this_thread
-//------------------------------------------------------------------------------
-
-thread::id this_thread::get_id() {
-#if defined(_TTHREAD_WIN32_)
- return thread::id((unsigned long int) GetCurrentThreadId());
-#elif defined(_TTHREAD_POSIX_)
- return _pthread_t_to_ID(pthread_self());
-#endif
-}
-
-namespace chrono {
-namespace system_clock {
-uint64_t now() {
- uint64_t time = 0;
-#ifdef _WIN32
- FILETIME tv;
- GetSystemTimeAsFileTime(&tv);
- time = (((uint64_t) tv.dwHighDateTime) << 32) + tv.dwLowDateTime;
- time /= 10000;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- time += tv.tv_sec * 1000;
- time += tv.tv_usec / 1000;
-#endif
- return time;
-}
-}
-}
-
-}
diff --git a/src/uscxml/concurrency/tinythread.h b/src/uscxml/concurrency/tinythread.h
deleted file mode 100644
index e5e5e25..0000000
--- a/src/uscxml/concurrency/tinythread.h
+++ /dev/null
@@ -1,726 +0,0 @@
-/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
-Copyright (c) 2010-2012 Marcus Geelnard
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software. This version was altered!
-
- 3. This notice may not be removed or altered from any source
- distribution.
-*/
-
-#ifndef _TINYTHREAD_H_
-#define _TINYTHREAD_H_
-
-#include "uscxml/Common.h"
-//#include <ostream>
-
-/// @file
-/// @mainpage TinyThread++ API Reference
-///
-/// @section intro_sec Introduction
-/// TinyThread++ is a minimal, portable implementation of basic threading
-/// classes for C++.
-///
-/// They closely mimic the functionality and naming of the C++11 standard, and
-/// should be easily replaceable with the corresponding std:: variants.
-///
-/// @section port_sec Portability
-/// The Win32 variant uses the native Win32 API for implementing the thread
-/// classes, while for other systems, the POSIX threads API (pthread) is used.
-///
-/// @section class_sec Classes
-/// In order to mimic the threading API of the C++11 standard, subsets of
-/// several classes are provided. The fundamental classes are:
-/// @li tthread::thread
-/// @li tthread::mutex
-/// @li tthread::recursive_mutex
-/// @li tthread::condition_variable
-/// @li tthread::lock_guard
-/// @li tthread::fast_mutex
-///
-/// @section misc_sec Miscellaneous
-/// The following special keywords are available: #thread_local.
-///
-/// For more detailed information (including additional classes), browse the
-/// different sections of this documentation. A good place to start is:
-/// tinythread.h.
-
-// Which platform are we on?
-#if !defined(_TTHREAD_PLATFORM_DEFINED_)
-#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
-#define _TTHREAD_WIN32_
-#include <boost/cstdint.hpp>
-#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
-#else
-#include <pthread.h>
-#include <signal.h>
-#include <sched.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <inttypes.h>
-#endif
-
-// Generic includes
-#include <ostream>
-
-/// TinyThread++ version (major number).
-#define TINYTHREAD_VERSION_MAJOR 1
-/// TinyThread++ version (minor number).
-#define TINYTHREAD_VERSION_MINOR 1
-/// TinyThread++ version (full version).
-#define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR)
-
-// Do we have a fully featured C++11 compiler?
-#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
-#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_
-#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;
-#else
-#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
- name(const name&); \
- name& operator=(const name&);
-#endif
-
-/// @def thread_local
-/// Thread local storage keyword.
-/// A variable that is declared with the @c thread_local keyword makes the
-/// value of the variable local to each thread (known as thread-local storage,
-/// or TLS). Example usage:
-/// @code
-/// // This variable is local to each thread.
-/// thread_local int variable;
-/// @endcode
-/// @note The @c thread_local keyword is a macro that maps to the corresponding
-/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard
-/// allows for non-trivial types (e.g. classes with constructors and
-/// destructors) to be declared with the @c thread_local keyword, most pre-C++11
-/// compilers only allow for trivial types (e.g. @c int). So, to guarantee
-/// portable code, only use trivial types for thread local storage.
-/// @note This directive is currently not supported on Mac OS X (it will give
-/// a compiler error), since compile-time TLS is not supported in the Mac OS X
-/// executable format. Also, some older versions of MinGW (before GCC 4.x) do
-/// not support this directive.
-/// @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
-#endif
-
-
-/// Main name space for TinyThread++.
-/// This namespace is more or less equivalent to the @c std namespace for the
-/// C++11 thread classes. For instance, the tthread::mutex class corresponds to
-/// the std::mutex class.
-namespace tthread {
-
-unsigned long long int timeStamp();
-
-/// Mutex class.
-/// This is a mutual exclusion object for synchronizing access to shared
-/// memory areas for several threads. The mutex is non-recursive (i.e. a
-/// program may deadlock if the thread that owns a mutex object calls lock()
-/// on that object).
-/// @see recursive_mutex
-
-class USCXML_API mutex {
-public:
- /// Constructor.
- mutex()
-#if defined(_TTHREAD_WIN32_)
- : 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;
- }
- 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;
-};
-
-/// Recursive mutex class.
-/// This is a mutual exclusion object for synchronizing access to shared
-/// memory areas for several threads. The mutex is recursive (i.e. a thread
-/// may lock the mutex several times, as long as it unlocks the mutex the same
-/// number of times).
-/// @see mutex
-class USCXML_API recursive_mutex {
-public:
- /// Constructor.
- recursive_mutex() {
-#if defined(_TTHREAD_WIN32_)
- InitializeCriticalSection(&mHandle);
-#else
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&mHandle, &attr);
-#endif
- }
-
- /// Destructor.
- ~recursive_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);
-#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_)
- return TryEnterCriticalSection(&mHandle) ? true : false;
-#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_)
- LeaveCriticalSection(&mHandle);
-#else
- pthread_mutex_unlock(&mHandle);
-#endif
- }
-
- //_TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
-
-private:
-#if defined(_TTHREAD_WIN32_)
- CRITICAL_SECTION mHandle;
-#else
- pthread_mutex_t mHandle;
-#endif
-
- friend class condition_variable;
-};
-
-/// Lock guard class.
-/// The constructor locks the mutex, and the destructor unlocks the mutex, so
-/// the mutex will automatically be unlocked when the lock guard goes out of
-/// scope. Example usage:
-/// @code
-/// mutex m;
-/// int counter;
-///
-/// void increment()
-/// {
-/// lock_guard<mutex> guard(m);
-/// ++ counter;
-/// }
-/// @endcode
-
-template <class T>
-class USCXML_API 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;
-};
-
-/// Condition variable class.
-/// This is a signalling object for synchronizing the execution flow for
-/// several threads. Example usage:
-/// @code
-/// // Shared data and associated mutex and condition variable objects
-/// int count;
-/// mutex m;
-/// condition_variable cond;
-///
-/// // Wait for the counter to reach a certain number
-/// void wait_counter(int targetCount)
-/// {
-/// lock_guard<mutex> guard(m);
-/// while(count < targetCount)
-/// cond.wait(m);
-/// }
-///
-/// // Increment the counter, and notify waiting threads
-/// void increment()
-/// {
-/// lock_guard<mutex> guard(m);
-/// ++ count;
-/// cond.notify_all();
-/// }
-/// @endcode
-class USCXML_API condition_variable {
-public:
- /// Constructor.
-#if defined(_TTHREAD_WIN32_)
- condition_variable();
-#else
- condition_variable() {
- pthread_cond_init(&mHandle, NULL);
- }
-#endif
-
- /// Destructor.
-#if defined(_TTHREAD_WIN32_)
- ~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) {
-#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(0);
- aMutex.lock();
-#else
- pthread_cond_wait(&mHandle, &aMutex.mHandle);
-#endif
- }
-
- template <class _mutexT>
- inline void wait_for(_mutexT &aMutex, unsigned int ms) {
-#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(ms);
- aMutex.lock();
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
-
- struct timespec ts;
- ts.tv_sec = tv.tv_sec + (ms / 1000);
- ts.tv_nsec = (tv.tv_usec * 1000); // convert tv microseconds to nanoseconds
- ts.tv_nsec += (ms % 1000) * 1000000; // add millisecond part of wait time
- pthread_cond_timedwait(&mHandle, &aMutex.mHandle, &ts);
-#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.
-#if defined(_TTHREAD_WIN32_)
- void notify_one();
-#else
- 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.
-#if defined(_TTHREAD_WIN32_)
- void notify_all();
-#else
- inline void notify_all() {
- pthread_cond_broadcast(&mHandle);
- }
-#endif
-
- //_TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
-
-private:
-#if defined(_TTHREAD_WIN32_)
- void _wait(unsigned int ms);
- 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;
-#endif
-};
-
-
-/// Thread class.
-class USCXML_API thread {
-public:
-#if defined(_TTHREAD_WIN32_)
- typedef HANDLE native_handle_type;
-#else
- typedef pthread_t native_handle_type;
-#endif
-
- class id;
-
- /// 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.
-#if defined(_TTHREAD_WIN32_)
- unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
-#endif
-
- // This is the internal thread wrapper function.
-#if defined(_TTHREAD_WIN32_)
- static unsigned WINAPI wrapper_function(void * aArg);
-#else
- static void * wrapper_function(void * aArg);
-#endif
-};
-
-/// Thread ID.
-/// The thread ID is a unique identifier for each thread.
-/// @see thread::get_id()
-class USCXML_API 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;
-};
-
-
-// Related to <ratio> - minimal to be able to support chrono.
-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 USCXML_API 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.
-
-namespace system_clock {
-uint64_t now();
-}
-
-}
-
-/// 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() {
-#if defined(_TTHREAD_WIN32_)
- 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) {
-#if defined(_TTHREAD_WIN32_)
- 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));
-#endif
-}
-}
-
-}
-
-// Define/macro cleanup
-#undef _TTHREAD_DISABLE_ASSIGNMENT
-
-#endif // _TINYTHREAD_H_