This file is indexed.

/usr/include/x86_64-linux-gnu/qcc/ThreadPool.h is in liballjoyn-common-dev-1604 16.04a-3.

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/**
 * @file
 *
 * Simple ThreadPool using Timers and Alarms
 */

/******************************************************************************
 * Copyright AllSeen Alliance. All rights reserved.
 *
 *    Permission to use, copy, modify, and/or distribute this software for any
 *    purpose with or without fee is hereby granted, provided that the above
 *    copyright notice and this permission notice appear in all copies.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 ******************************************************************************/

#ifndef _QCC_THREADPOOL_H
#define _QCC_THREADPOOL_H

#include <map>

#include <qcc/Timer.h>
#include <qcc/Event.h>
#include <qcc/Ptr.h>

namespace qcc {

class ThreadPool;

/**
 * A class in the spirit of the Java Runnable object that is used to define an
 * object which is executable by a ThreadPool.
 *
 * In order to ask the ThreadPool to execute a task, inherit from the Runnable
 * class and provide a Run() method.
 *
 * Typically one extends the Runnable object with member data corresponding to
 * the deferred variables needed by the Run() method.  This kind of object is
 * called a closure.  Since the data must be kept outside of the context of the
 * function or method that asks for execution of the Runnable, it must be kept
 * on the heap.
 *
 * The AllJoyn common OS abstractions library provides a ManagedObj (similar to
 * smart pointers but using references) to help with this kind of need, but it
 * has problems if you want to cast from one kind of ManagedObj to another (see
 * the single parameter constructor and explicit call to the destructor of the
 * enclosed type.  Since we need the cast behavior, we use the Ptr intrusive
 * smart pointer class to manage our runnable closures.
 */
class Runnable : public qcc::RefCountBase, public qcc::AlarmListener {
  public:

    /**
     * Construct a Runnable object suitable for use by a ThreadPool
     */
    Runnable() : m_threadpool(NULL) { }

    /**
     * Destroy a Runnable object.
     */
    virtual ~Runnable() { m_threadpool = NULL; }

    /**
     * This method is called by the ThreadPool when the Runnable object is
     * dispatched to a thread.  A client of the thread pool is expected to
     * define a method in a derived class that does useful work when Run() is
     * called.
     */
    virtual void Run(void) { };

  private:
    /**
     * ThreadPool must be a friend in order to make AlarmTriggered an accessible
     * base class method of a user's Runnable, and to allow the ThreadPool to
     * set a pointer to itself here to allow for notifications.
     */
    friend class ThreadPool;

    /**
     * AlarmTriggered is the method that is called to dispatch an alarm.
     * Our Run() methods are driven by alarm expirations that happen to
     * always occur immediately.
     *
     * Note that the enclosing runnable object is automatically deleted
     * afte the Run method is executed.
     */
    virtual void AlarmTriggered(const Alarm& alarm, QStatus reason);

    /**
     * Private method used by the thread pool to tell this object how to contact
     * the thread pool when the reference to the runnable closure is no longer
     * needed.
     */
    void SetThreadPool(ThreadPool* threadpool)
    {
        m_threadpool = threadpool;
    }

    /**
     * A reference back to the thread pool that causes the run method to be
     * called.  We need this reference so the thread pool can hook a "done"
     * event since it would otherwise be unaware of the execution of the
     * runderlying timer alarm callback that it arranged to be called.
     */
    ThreadPool* m_threadpool;
};

/**
 * A class in the spirit of the Java ThreadPoolExecutor object that is used
 * to provide a simple way to execute tasks in the context of a separate
 * thread.
 *
 * In order to ask a ThreadPool to execute a task, one must inherit from the
 * Runnable class and provide a Run() method.
 */
class ThreadPool {
  public:
    /**
     * Construct a thread pool with a given name and pool size.
     *
     * @param name     The name of the thread pool (used in logging).
     * @param poolsize The number of threads available in the pool.
     */
    ThreadPool(const char* name, uint32_t poolsize);

    /**
     * Destroy a thread pool.
     */
    virtual ~ThreadPool();

    /**
     * Request that we cancel all of our dispatched threads.
     */
    QStatus Stop();

    /**
     * Wait for all of the threads in our associated timer to exit.  Once
     * this happens, it is safe for us to finish tearing down our object.
     * Note that this call can block or a time limited only by the execution
     * time of the threads dispatched.
     */
    QStatus Join();

    /**
     * Determine the underlying concurrency of the thread pool.
     *
     * Convenience function to get the number of threads available in the thread pool.
     * This is different than GetN() which returns the number of threads that are
     * currently executing or waiting to execute a closure.
     *
     * @return The number of concurrently execution tasks possible in this thread pool.
     */
    uint32_t GetConcurrency(void)
    {
        return m_poolsize;
    }

    /**
     * Determine how many Runnable tasks are pending on the thread pool.
     *
     * Convenience function to get the number of threads currently executing or
     * waiting to execute.  This is different than GetConcurrency() which
     * returns the number of threads in the thread pool (which may or may not be
     * currently executing or waiting to execute.
     *
     * @return The number of Runnable closures which represent either pending
     *         execution or are currently executing runnable tasks.
     */
    uint32_t GetN(void);

    /**
     * Execute a Runnable task one one of the threads of the thread pool.
     *
     * The execute method takes a pointer to a Runnable object.  This object
     * acts as a closure which essentialy is a pre-packaged function call.  The
     * function is called Run() in this case.  Since we need to keep the package
     * around until Run() actually executes, and the thread that calls Execute()
     * may be long gone by the time this happens, the Runnable must be allocated
     * on the heap.  Only the thread pool knows when the Runnable is no longer
     * needed, so it takes responsibility for managing the memory of the runnable
     * when Execute is called.
     *
     * Each call to Execute must provide a pointer to a unique Runnable
     *
     * @param runnable A Ptr (smart pointer) to a Runnable Object providing the
     *                 Run() method which one of the threads in this thread pool
     *                 will execute.
     *
     * @return
     *      - #ER_OK if the execute request was successful
     *      - #ER_THREADPOOL_EXHAUSTED if the thread pool has previously reached its specified concurrency.
     */
    QStatus Execute(Ptr<Runnable> runnable);

    /**
     * Wait for a thread to become available for use.
     *
     * Since AllJoyn is at its heart a distributed network application, and what
     * drives the execution of our threads will ultimately be network traffic,
     * we need to be able to apply backpressure to the network to avoid
     * exhausting all available resources.  We do this by providing a method which
     * allows a caller to put itself to sleep until a thread beomes available.
     *
     * If the caller thread happens to be the thread that is reading messages off
     * of the network, it will put itself to sleep.  This will stop the network
     * destination from pulling bits out of its queue and will result in, for example,
     * the TCP receive queue filling.  This will, in turn, apply backpressure to the
     * sender which will rate limit the system.  This prevents unbounded resource
     * allocation of corresponding threads and memory.
     *
     * @return ER_OK when a thread becomes available, or a general error if one happens.
     */
    QStatus WaitForAvailableThread(void);

  private:
    /**
     * Runnable must be a friend in order to call back and tell us that it has
     * finished executing.  Since this affects the memory management contract
     * between the Runnable and ThreadPool objects, we don't let anyone else
     * but Runnable make this call.
     */
    friend class Runnable;

    /**
     * Assignment operator is private - ThreadPools cannot be assigned.
     */
    ThreadPool& operator=(const ThreadPool& other);

    /**
     * Copy constructor is private - ThreadPools cannot be copied.
     */
    ThreadPool(const ThreadPool& other);

    /**
     * A flag to remind if the thread pool is stopping or stopped.
     */
    bool m_stopping;

    /**
     * A mutex to protect the underlying data structures.
     */
    qcc::Mutex m_lock;

    /**
     * An event to allow callers to wait until a thread becomes available
     * in the pool.
     */
    qcc::Event m_event;

    /**
     * The maximum number of concurrent threads executing in this thread pool.
     */
    uint32_t m_poolsize;

    /**
     * We need to hold a reference to an underlying Runnable object while we
     * wait for its Run() method to be executed.  The Runnable object acts as a
     * closure that a user will use to keep required variables.  When the Run()
     * method is done executing, we release the reference to the runnable managed
     * object by deleting the corresponding entry in the closure map.
     */
    typedef std::map<Runnable*, Ptr<Runnable> > RunnableEntry;
    RunnableEntry m_closures;

    /**
     * When the AlarmTriggered callback of the AlarmListener base class of the
     * Runnable is called by the Timer, it will call the user's Run() function
     * and then call back here to let us know that it has finished executing.
     * That tells us that we can clean up any resources we may be holding.  That
     * just means releasing our reference to the Ptr that holds the ulitmate
     * reference to the runnable.  If we can't find a closure, we have screwed
     * up massively and we should just die.
     */
    void Release(Runnable* runnable);

    /**
     * The timer that actually does all of the work of dispatching threads and
     * essentially doing all of the work of the thread pool.
     */
    qcc::Timer m_dispatcher;
};

} // namespace qcc

#endif