1 /** @file taskpool.h  Pool of tasks.
2  *
3  * @authors Copyright © 2013-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * LGPL: http://www.gnu.org/licenses/lgpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14  * General Public License for more details. You should have received a copy of
15  * the GNU Lesser General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #ifndef LIBDENG2_TASKPOOL_H
20 #define LIBDENG2_TASKPOOL_H
21 
22 #include "../Observers"
23 #include <QObject>
24 #include <functional>
25 
26 namespace de {
27 
28 class Task;
29 
30 /**
31  * Pool of concurrent tasks. @ingroup concurrency
32  *
33  * The application uses a single, shared pool of background threads regardless
34  * of how many instances of TaskPool are created. One should use a separate
35  * TaskPool instance for each group of concurrent tasks whose state needs to be
36  * observed as a whole.
37  *
38  * While TaskPool allows the user to monitor whether all tasks are done and
39  * block until that time arrives (TaskPool::waitForDone()), no facilities are
40  * provided for interrupting any of the started tasks. If that is required, the
41  * Task instances in question should periodically check for an abort condition
42  * and shut themselves down nicely when requested.
43  *
44  * A Task is considered done/finished when it has exited its Task::runTask() method.
45  */
46 class DENG2_PUBLIC TaskPool : public QObject
47 {
48     Q_OBJECT
49 
50 public:
51     enum Priority
52     {
53         LowPriority    = 0,
54         MediumPriority = 1,
55         HighPriority   = 2
56     };
57 
58     class IPool
59     {
60     public:
61         virtual void taskFinishedRunning(Task &) = 0;
62     };
63 
64     typedef std::function<void ()> TaskFunction;
65 
66     DENG2_DEFINE_AUDIENCE2(Done, void taskPoolDone(TaskPool &))
67 
68 public:
69     TaskPool();
70 
71     /**
72      * Destroys the task pool when all running tasks have finished. This method will
73      * always return immediately and the public-facing TaskPool object will be deleted,
74      * but the private instance will exist until all the tasks have finished running.
75      */
76     virtual ~TaskPool();
77 
78     /**
79      * Starts a new concurrent task. Ownership of the task is given to the
80      * pool.
81      *
82      * @param task      Task instance. Ownership given.
83      * @param priority  Priority of the task.
84      */
85     void start(Task *task, Priority priority = LowPriority);
86 
87     void start(TaskFunction taskFunction, Priority priority = LowPriority);
88 
89     /**
90      * Blocks execution until all running tasks have finished. A Task is considered
91      * finished when it has exited its Task::runTask() method.
92      */
93     void waitForDone();
94 
95     /**
96      * Determines if all started tasks have finished.
97      */
98     bool isDone() const;
99 
100 signals:
101     void allTasksDone();
102 
103 private:
104     DENG2_PRIVATE(d)
105 };
106 
107 } // namespace de
108 
109 #endif // LIBDENG2_TASKPOOL_H
110