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