From 308903dc9185223e015333c674b419b1ef45cb15 Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Fri, 24 Jan 2020 13:52:37 +0100 Subject: [PATCH] Revert to c3ae70461061a9546a430147a4aabc8960845d19 until the condition_variable problem is solved --- simgear/threads/SGThread.cxx | 232 +++++++++++++++++++++++------------ 1 file changed, 153 insertions(+), 79 deletions(-) diff --git a/simgear/threads/SGThread.cxx b/simgear/threads/SGThread.cxx index 7da62bb7..6123966d 100644 --- a/simgear/threads/SGThread.cxx +++ b/simgear/threads/SGThread.cxx @@ -35,85 +35,6 @@ #include #include -#if _WIN32 -# include -# include -#else -# include -# include -# include -# include -#endif - -struct SGWaitCondition::PrivateData { - PrivateData(void) - { - } - ~PrivateData(void) - { - } - - void signal(void) - { - bool waiter; - { - std::lock_guard lock(_mutex); - waiter = !ready; - ready = true; - } - if (waiter) { - _condition.notify_one(); - } - } - - void broadcast(void) - { - bool waiter; - { - std::lock_guard lock(_mutex); - waiter = !ready; - ready = true; - } - if (waiter) { - _condition.notify_all(); - } - } - - void wait(std::mutex& mutex) - { - std::unique_lock lock(_mutex); - - mutex.unlock(); - _condition.wait(lock, [this]{ return ready; } ); - mutex.lock(); - - ready = false; - } - - bool wait(std::mutex& mutex, unsigned msec) - { - auto timeout = std::chrono::milliseconds(msec); - std::unique_lock lock(mutex); - - try { - mutex.unlock(); - _condition.wait_for(lock, timeout, [this]{ return ready; } ); - mutex.lock(); - - ready = false; - } catch (std::runtime_error &ex) { - return false; - } - return true; - } - - std::mutex _mutex; - std::condition_variable _condition; - -private: - bool ready = false; -}; - struct SGThread::PrivateData { PrivateData() { @@ -162,6 +83,159 @@ struct SGThread::PrivateData { bool _started = false; }; +#if _WIN32 + +///////////////////////////////////////////////////////////////////////////// +/// win32 threads +///////////////////////////////////////////////////////////////////////////// + +#include +#include + +struct SGWaitCondition::PrivateData { + ~PrivateData(void) + { + // The waiters list should be empty anyway + _mutex.lock(); + while (!_pool.empty()) { + CloseHandle(_pool.front()); + _pool.pop_front(); + } + _mutex.unlock(); + } + + void signal(void) + { + _mutex.lock(); + if (!_waiters.empty()) + SetEvent(_waiters.back()); + _mutex.unlock(); + } + + void broadcast(void) + { + _mutex.lock(); + for (std::list::iterator i = _waiters.begin(); i != _waiters.end(); ++i) + SetEvent(*i); + _mutex.unlock(); + } + + bool wait(std::mutex& externalMutex, DWORD msec) + { + _mutex.lock(); + if (_pool.empty()) + _waiters.push_front(CreateEvent(NULL, FALSE, FALSE, NULL)); + else + _waiters.splice(_waiters.begin(), _pool, _pool.begin()); + std::list::iterator i = _waiters.begin(); + _mutex.unlock(); + + externalMutex.unlock(); + + DWORD result = WaitForSingleObject(*i, msec); + + externalMutex.lock(); + + _mutex.lock(); + if (result != WAIT_OBJECT_0) + result = WaitForSingleObject(*i, 0); + _pool.splice(_pool.begin(), _waiters, i); + _mutex.unlock(); + + return result == WAIT_OBJECT_0; + } + + void wait(std::mutex& externalMutex) + { + wait(externalMutex, INFINITE); + } + + // Protect the list of waiters + std::mutex _mutex; + + std::list _waiters; + std::list _pool; +}; + +#else +///////////////////////////////////////////////////////////////////////////// +/// posix threads +///////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +struct SGWaitCondition::PrivateData { + PrivateData(void) + { + int err = pthread_cond_init(&_condition, NULL); + assert(err == 0); + (void)err; + } + ~PrivateData(void) + { + int err = pthread_cond_destroy(&_condition); + assert(err == 0); + (void)err; + } + + void signal(void) + { + int err = pthread_cond_signal(&_condition); + assert(err == 0); + (void)err; + } + + void broadcast(void) + { + int err = pthread_cond_broadcast(&_condition); + assert(err == 0); + (void)err; + } + + void wait(std::mutex& mutex) + { + int err = pthread_cond_wait(&_condition, mutex.native_handle()); + assert(err == 0); + (void)err; + } + + bool wait(std::mutex& mutex, unsigned msec) + { + struct timespec ts; +#ifdef HAVE_CLOCK_GETTIME + if (0 != clock_gettime(CLOCK_REALTIME, &ts)) + return false; +#else + struct timeval tv; + if (0 != gettimeofday(&tv, NULL)) + return false; + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#endif + + ts.tv_nsec += 1000000*(msec % 1000); + if (1000000000 <= ts.tv_nsec) { + ts.tv_nsec -= 1000000000; + ts.tv_sec += 1; + } + ts.tv_sec += msec / 1000; + + int evalue = pthread_cond_timedwait(&_condition, mutex.native_handle(), &ts); + if (evalue == 0) + return true; + + assert(evalue == ETIMEDOUT); + return false; + } + + pthread_cond_t _condition; +}; + +#endif + SGThread::SGThread() : _privateData(new PrivateData) {