add queen mary DSP library
[ardour2.git] / libs / qm-dsp / thread / AsynchronousTask.h
blobd9d7d872c91263538bb4e8b72c4ec6b76c7e227d
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
3 /*
4 QM DSP Library
6 Centre for Digital Music, Queen Mary, University of London.
7 This file Copyright 2009 QMUL.
8 */
10 #ifndef _ASYNCHRONOUS_TASK_H_
11 #define _ASYNCHRONOUS_TASK_H_
13 #include "Thread.h"
15 #include <iostream>
17 /**
18 * AsynchronousTask provides a thread pattern implementation for
19 * threads which are used to perform a series of similar operations in
20 * parallel with other threads of the same type.
22 * For example, a thread used to calculate FFTs of a particular block
23 * size in the context of a class that needs to calculate many block
24 * sizes of FFT at once may be a candidate for an AsynchronousTask.
26 * The general use pattern is:
28 * caller -> request thread A calculate something
29 * caller -> request thread B calculate something
30 * caller -> request thread C calculate something
31 * caller -> wait for threads A, B, and C
33 * Here threads A, B, and C may be AsynchronousTasks. An important
34 * point is that the caller must be prepared to block when waiting for
35 * these threads to complete (i.e. they are started asynchronously,
36 * but testing for completion is synchronous).
38 class AsynchronousTask : public Thread
40 public:
41 AsynchronousTask() :
42 m_todo("AsynchronousTask: task to perform"),
43 m_done("AsynchronousTask: task complete"),
44 m_inTask(false),
45 m_finishing(false)
47 start();
49 virtual ~AsynchronousTask()
51 m_todo.lock();
52 m_finishing = true;
53 m_todo.signal();
54 m_todo.unlock();
55 wait();
58 // Subclass must provide methods to request task and obtain
59 // results, which the caller calls. The method that requests a
60 // new task should set up any internal state and call startTask(),
61 // which then calls back on the subclass implementation of
62 // performTask from within its work thread. The method that
63 // obtains results should call awaitTask() and then return any
64 // results from internal state.
66 protected:
67 void startTask() {
68 m_done.lock();
69 m_todo.lock();
70 m_inTask = true;
71 m_todo.signal();
72 m_todo.unlock();
74 void awaitTask() {
75 m_done.wait();
76 m_done.unlock();
79 virtual void performTask() = 0;
81 private:
82 virtual void run() {
83 m_todo.lock();
84 while (1) {
85 while (!m_inTask && !m_finishing) {
86 m_todo.wait();
88 if (m_finishing) {
89 m_done.lock();
90 m_inTask = false;
91 m_done.signal();
92 m_done.unlock();
93 break;
95 performTask();
96 m_done.lock();
97 m_inTask = false;
98 m_done.signal();
99 m_done.unlock();
101 m_todo.unlock();
104 Condition m_todo;
105 Condition m_done;
106 bool m_inTask;
107 bool m_finishing;
110 #endif