comparison thread/Thread.h @ 63:0dcbce5d7dce

* Add AsynchronousTask abstraction
author cannam
date Tue, 12 May 2009 21:04:25 +0000
parents b63f1ccbc9b6
children 2af6edd98dfa
comparison
equal deleted inserted replaced
62:b63f1ccbc9b6 63:0dcbce5d7dce
103 { 103 {
104 public: 104 public:
105 Condition(std::string name); 105 Condition(std::string name);
106 ~Condition(); 106 ~Condition();
107 107
108 //!!! NO -- reproducing more conventional lock/wait 108 // Condition bundles a pthread-style condition variable and mutex
109 109 // into one class.
110 // To wait on a condition, either simply call wait(), or call 110
111 // lock() and then wait() (perhaps testing some state in between). 111 // To wait on a condition, call lock(), test termination variables
112 // To signal a condition, call signal(). 112 // as appropriate, and then wait(). The condition will be
113 113 // unlocked for the duration of the wait() call, which will end
114 // Although any thread may signal on a given condition, only one 114 // when the condition is signalled. The condition will be locked
115 // thread should ever wait on any given condition object -- 115 // again when wait() returns.
116 // otherwise there will be a race conditions in the logic that 116 //
117 // avoids the thread code having to track whether the condition's 117 // To signal a condition, call signal(). If the waiting thread
118 // mutex is locked or not. If that is your requirement, this 118 // will be performing tests between its own lock() and wait(),
119 // Condition wrapper is not for you. 119 // then the signalling thread should also lock() before it signals
120 // (and then unlock afterwards). If the signalling thread always
121 // locks the mutex during signalling, then the waiting thread
122 // knows that signals will only happen during wait() and not be
123 // missed at other times.
124
120 void lock(); 125 void lock();
121 void unlock(); 126 void unlock();
122 void wait(int us = 0); 127 void wait(int us = 0);
123 128
124 void signal(); 129 void signal();
139 #ifdef DEBUG_CONDITION 144 #ifdef DEBUG_CONDITION
140 std::string m_name; 145 std::string m_name;
141 #endif 146 #endif
142 }; 147 };
143 148
144 #endif 149 class AsynchronousTask : public Thread
150 {
151 public:
152 AsynchronousTask() :
153 m_todo("AsynchronousTask: task to perform"),
154 m_done("AsynchronousTask: task complete"),
155 m_inTask(false),
156 m_finishing(false)
157 {
158 start();
159 }
160 virtual ~AsynchronousTask()
161 {
162 m_finishing = true;
163 m_todo.signal();
164 wait();
165 }
166
167 // subclass must provide methods to request task and obtain
168 // results
169
170 protected:
171 void startTask() {
172 m_todo.lock();
173 m_inTask = true;
174 m_todo.signal();
175 m_done.lock();
176 m_todo.unlock();
177 }
178 void awaitTask() {
179 while (m_inTask) m_done.wait();
180 m_done.unlock();
181 }
182
183 virtual void performTask() = 0;
184
185 private:
186 virtual void run() {
187 m_todo.lock();
188 while (!m_finishing) {
189 while (!m_inTask && !m_finishing) m_todo.wait();
190 if (m_finishing) break;
191 if (m_inTask) {
192 performTask();
193 m_inTask = false;
194 m_done.signal();
195 }
196 }
197 m_todo.unlock();
198 }
199
200 Condition m_todo;
201 Condition m_done;
202 bool m_inTask;
203 bool m_finishing;
204 };
205
206 #endif