comparison thread/AsynchronousTask.h @ 292:b97f4f926f48

* Pull out AsynchronousTask into its own header * Add a fixed-size block allocator based on FSBAllocator
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 14 May 2009 12:45:08 +0000
parents
children 09aba2ccd94a
comparison
equal deleted inserted replaced
291:37bbd2f605f8 292:b97f4f926f48
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 QM DSP Library
5
6 Centre for Digital Music, Queen Mary, University of London.
7 This file Copyright 2009 QMUL.
8 */
9
10 #ifndef _ASYNCHRONOUS_TASK_H_
11 #define _ASYNCHRONOUS_TASK_H_
12
13 #include "Thread.h"
14
15 /**
16 * AsynchronousTask provides a thread pattern implementation for
17 * threads which are used to perform a series of similar operations in
18 * parallel with other threads of the same type.
19 *
20 * For example, a thread used to calculate FFTs of a particular block
21 * size in the context of a class that needs to calculate many block
22 * sizes of FFT at once may be a candidate for an AsynchronousTask.
23 *
24 * The general use pattern is:
25 *
26 * caller -> request thread A calculate something
27 * caller -> request thread B calculate something
28 * caller -> request thread C calculate something
29 * caller -> wait for threads A, B, and C
30 *
31 * Here threads A, B, and C may be AsynchronousTasks. An important
32 * point is that the caller must be prepared to block when waiting for
33 * these threads to complete (i.e. they are started asynchronously,
34 * but testing for completion is synchronous).
35 */
36 class AsynchronousTask : public Thread
37 {
38 public:
39 AsynchronousTask() :
40 m_todo("AsynchronousTask: task to perform"),
41 m_done("AsynchronousTask: task complete"),
42 m_inTask(false),
43 m_finishing(false)
44 {
45 start();
46 }
47 virtual ~AsynchronousTask()
48 {
49 m_finishing = true;
50 m_todo.signal();
51 wait();
52 }
53
54 // Subclass must provide methods to request task and obtain
55 // results, which the caller calls. The method that requests a
56 // new task should set up any internal state and call startTask(),
57 // which then calls back on the subclass implementation of
58 // performTask from within its work thread. The method that
59 // obtains results should call awaitTask() and then return any
60 // results from internal state.
61
62 protected:
63 void startTask() {
64 m_todo.lock();
65 m_inTask = true;
66 m_todo.signal();
67 m_done.lock();
68 m_todo.unlock();
69 }
70 void awaitTask() {
71 while (m_inTask) m_done.wait();
72 m_done.unlock();
73 }
74
75 virtual void performTask() = 0;
76
77 private:
78 virtual void run() {
79 m_todo.lock();
80 while (!m_finishing) {
81 while (!m_inTask && !m_finishing) {
82 m_todo.wait();
83 }
84 if (m_finishing) {
85 break;
86 }
87 if (m_inTask) {
88 performTask();
89 m_inTask = false;
90 m_done.signal();
91 }
92 }
93 m_todo.unlock();
94 }
95
96 Condition m_todo;
97 Condition m_done;
98 bool m_inTask;
99 bool m_finishing;
100 };
101
102 #endif