diff --git a/src/lib/utils/thread.cpp b/src/lib/utils/thread.cpp index 205a7d69..ed2fc961 100755 --- a/src/lib/utils/thread.cpp +++ b/src/lib/utils/thread.cpp @@ -84,25 +84,54 @@ WaitThread::~WaitThread() { void WaitThread::stop() { pthread_mutex_lock(&m_mutex); pthread_cond_signal(&m_cond); - pthread_mutex_unlock(&m_mutex); Thread::stop(); + pthread_mutex_unlock(&m_mutex); } bool WaitThread::join() { - pthread_mutex_lock(&m_mutex); - pthread_cond_signal(&m_cond); - pthread_mutex_unlock(&m_mutex); + stop(); return Thread::join(); } bool WaitThread::Wait(int seconds) { + pthread_mutex_lock(&m_mutex); struct timespec t; clockGettime(&t); t.tv_sec += seconds; - pthread_mutex_lock(&m_mutex); pthread_cond_timedwait(&m_cond, &m_mutex, &t); pthread_mutex_unlock(&m_mutex); return isRunning(); } + +NotifiableThread::NotifiableThread() + : WaitThread(), m_notified(false) { +} + +void NotifiableThread::notify() { + pthread_mutex_lock(&m_mutex); + pthread_cond_signal(&m_cond); + m_notified = true; + pthread_mutex_unlock(&m_mutex); +} + +bool NotifiableThread::waitNotified(int millis) { + pthread_mutex_lock(&m_mutex); + if (!m_notified) { + struct timespec t; + clockGettime(&t); + t.tv_sec += millis / 1000000000; + t.tv_nsec += (millis % 1000000000) * 1000000; + if (t.tv_nsec > 1000000000) { + t.tv_sec++; + t.tv_nsec -= 1000000000; + } + pthread_cond_timedwait(&m_cond, &m_mutex, &t); + } + bool notified = m_notified; + m_notified = false; + pthread_mutex_unlock(&m_mutex); + return notified; +} + } // namespace ebusd diff --git a/src/lib/utils/thread.h b/src/lib/utils/thread.h index de2e5e0b..d5b57278 100755 --- a/src/lib/utils/thread.h +++ b/src/lib/utils/thread.h @@ -1,6 +1,6 @@ /* * ebusd - daemon for communication with eBUS heating systems. - * Copyright (C) 2014-2018 John Baier , Roland Jax 2012-2014 + * Copyright (C) 2014-2020 John Baier , Roland Jax 2012-2014 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ namespace ebusd { /** \file lib/utils/thread.h */ /** - * wrapper class for pthread. + * Wrapper class for pthread. */ class Thread { public: @@ -82,7 +82,7 @@ class Thread { /** * Thread entry method to be overridden by derived class. */ - virtual void run() = 0; + virtual void run() = 0; // abstract private: @@ -134,7 +134,7 @@ class WaitThread : public Thread { bool Wait(int seconds); - private: + protected: /** the mutex for waiting. */ pthread_mutex_t m_mutex; @@ -143,6 +143,35 @@ class WaitThread : public Thread { }; +/** + * A @a WaitThread that can be waited on. + */ +class NotifiableThread : public WaitThread { + public: + /** + * Constructor. + */ + NotifiableThread(); + + /** + * Notify another thread currently in @a wait(). + */ + void notify(); + + /** + * Wait for getting notified up to the specified amount of time. + * @param millis the maximum number of milliseconds to wait. + * @return true if @a notify() was called while waiting. + */ + bool waitNotified(int millis); + + + private: + /** whether @a notify() was called while waiting. */ + bool m_notified; +}; + + /** * A simple mutex. */