Mercurial > hg > qm-dsp
changeset 63:0dcbce5d7dce
* Add AsynchronousTask abstraction
author | cannam |
---|---|
date | Tue, 12 May 2009 21:04:25 +0000 |
parents | b63f1ccbc9b6 |
children | 6cb2b3cd5356 |
files | thread/Thread.h |
diffstat | 1 files changed, 73 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/thread/Thread.h Tue May 12 17:56:58 2009 +0000 +++ b/thread/Thread.h Tue May 12 21:04:25 2009 +0000 @@ -105,18 +105,23 @@ Condition(std::string name); ~Condition(); - //!!! NO -- reproducing more conventional lock/wait - - // To wait on a condition, either simply call wait(), or call - // lock() and then wait() (perhaps testing some state in between). - // To signal a condition, call signal(). + // Condition bundles a pthread-style condition variable and mutex + // into one class. - // Although any thread may signal on a given condition, only one - // thread should ever wait on any given condition object -- - // otherwise there will be a race conditions in the logic that - // avoids the thread code having to track whether the condition's - // mutex is locked or not. If that is your requirement, this - // Condition wrapper is not for you. + // To wait on a condition, call lock(), test termination variables + // as appropriate, and then wait(). The condition will be + // unlocked for the duration of the wait() call, which will end + // when the condition is signalled. The condition will be locked + // again when wait() returns. + // + // To signal a condition, call signal(). If the waiting thread + // will be performing tests between its own lock() and wait(), + // then the signalling thread should also lock() before it signals + // (and then unlock afterwards). If the signalling thread always + // locks the mutex during signalling, then the waiting thread + // knows that signals will only happen during wait() and not be + // missed at other times. + void lock(); void unlock(); void wait(int us = 0); @@ -141,4 +146,61 @@ #endif }; +class AsynchronousTask : public Thread +{ +public: + AsynchronousTask() : + m_todo("AsynchronousTask: task to perform"), + m_done("AsynchronousTask: task complete"), + m_inTask(false), + m_finishing(false) + { + start(); + } + virtual ~AsynchronousTask() + { + m_finishing = true; + m_todo.signal(); + wait(); + } + + // subclass must provide methods to request task and obtain + // results + +protected: + void startTask() { + m_todo.lock(); + m_inTask = true; + m_todo.signal(); + m_done.lock(); + m_todo.unlock(); + } + void awaitTask() { + while (m_inTask) m_done.wait(); + m_done.unlock(); + } + + virtual void performTask() = 0; + +private: + virtual void run() { + m_todo.lock(); + while (!m_finishing) { + while (!m_inTask && !m_finishing) m_todo.wait(); + if (m_finishing) break; + if (m_inTask) { + performTask(); + m_inTask = false; + m_done.signal(); + } + } + m_todo.unlock(); + } + + Condition m_todo; + Condition m_done; + bool m_inTask; + bool m_finishing; +}; + #endif