This file is indexed.

/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