annotate thread/AsynchronousTask.h @ 374:3e5f13ac984f

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