Beatmup
context.h
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 
21 #include "basic_types.h"
22 #include "parallelism.h"
23 #include <string>
24 
25 
26 namespace Beatmup {
27 
28  /** \page ProgrammingModel Programming model
29  %Beatmup is thought as a toolset for building efficient signal and image processing pipelines.
30 
31  This page covers briefly few main concepts of a fairly simple programming model used in %Beatmup: *contexts*, *thread pools*, *tasks*, *jobs*
32  and *bitmaps*.
33 
34  \section secContext Context and thread pools
35  A Context instance mainly contains one or more thread pools that can execute processing actions (tasks). At least one Context instance (and
36  quite often just one) is required to do anything in %Beatmup.
37 
38  A thread pool is a bunch of threads and a queue of tasks. Tasks are submitted by the application in a pool and are executed in order.
39  A given thread pool can run only one task at a time, but it does so in multiple threads in parallel for speed.
40 
41  Thread pools work asynchronously with respect to the caller code: the tasks can be submitted by the application in a non-blocking call,
42  straight from a user interface managing thread for example. Context exposes necessary API entries to check whether a specific task is
43  completed or still waiting in the queue, to cancel a submitted task, to check exceptions thrown during task execution, etc.
44 
45  By default, when a thread pool is created, the number of threads it hosts is inferred from the hardware concurrency: typically, it is equal
46  to the number of logical CPU cores. This setting is likely to provide the best performance for computationally intensive tasks.
47  The number of threads in a pool can be further adjusted by calling Context::limitWorkerCount().
48  */
49 
50  namespace GL {
51  class RecycleBin;
52  }
53 
54  class AbstractBitmap;
55 
56  /**
57  Basic class: task and memory management, any kind of static data
58  */
59  class Context : public Object {
60  Context(const Context&) = delete; //!< disabling copying constructor
61  private:
62  class Impl;
64  GL::RecycleBin* recycleBin; //!< stores GPU garbage: resources managed by GPU and might be freed in the managing thread only
65 
66  public:
67  static const PoolIndex DEFAULT_POOL = 0;
68 
69  /**
70  An event listener (bunch of callbacks)
71  */
72  class EventListener {
73  public:
74  virtual ~EventListener() {}
75 
76  /**
77  Called when a new worker thread is created
78  */
79  virtual void threadCreated(PoolIndex pool) = 0;
80 
81  /**
82  Called when a worker thread finished
83  */
84  virtual void threadTerminating(PoolIndex pool) = 0;
85 
86  /**
87  Called when a task is successfully finished.
88  \param[in] pool The thread pool the task was run in
89  \param[in] task The task
90  \param[in] aborted If `true`, the task was aborted from outside
91  \returns `true` if the task is asked to be executed again. Note that even if `false` is returned, a repetition might be asked from outside.
92  */
93  virtual bool taskDone(PoolIndex pool, AbstractTask& task, bool aborted) = 0;
94 
95  /**
96  Called when a task fails.
97  \param[in] pool The thread pool the task was run in
98  \param[in] task The task
99  \param[in] ex Exception caught when the task is failed
100  */
101  virtual void taskFail(PoolIndex pool, AbstractTask& task, const std::exception& ex) = 0;
102 
103  /**
104  Called when GPU initialization failed.
105  \param[in] pool The thread pool the failure occurred in
106  \param[in] ex Exception caught
107  */
108  virtual void gpuInitFail(PoolIndex pool, const std::exception& ex) = 0;
109  };
110 
111  Context();
112  Context(const PoolIndex numThreadPools);
113  ~Context();
114 
115  /**
116  Performs a given task.
117  \param task The task
118  \param pool A thread pool to run the task in
119  \returns task execution time
120  */
121  float performTask(AbstractTask& task, const PoolIndex pool = DEFAULT_POOL);
122 
123  /**
124  Ensures a given task executed at least once.
125  \param task The task
126  \param abortCurrent if `true` and the same task is currently running, the abort signal is sent.
127  \param pool A thread pool to run the task in
128  */
129  void repeatTask(AbstractTask& task, bool abortCurrent, const PoolIndex pool = DEFAULT_POOL);
130 
131  /**
132  Adds a new task to the jobs queue.
133  \param task The task
134  \param pool A thread pool to run the task in
135  */
137 
138  /**
139  Adds a new persistent task to the jobs queue.
140  Persistent task is repeated until it decides itself to quit.
141  \param task The task
142  \param pool A thread pool to run the task in
143  */
145 
146  /**
147  Waits until a given job finishes.
148  \param job The job
149  \param pool Pool index
150  */
151  void waitForJob(Job job, const PoolIndex pool = DEFAULT_POOL);
152 
153  /**
154  Aborts a given submitted job.
155  \param job The job
156  \param pool Pool index
157  \return `true` if the job was interrupted while running.
158  */
159  bool abortJob(Job job, const PoolIndex pool = DEFAULT_POOL);
160 
161  /**
162  Blocks until all the submitted jobs are executed.
163  \param pool Pool index
164  */
165  void wait(const PoolIndex pool = DEFAULT_POOL);
166 
167  /**
168  Queries whether a given thread pool is busy with a task.
169  \param pool The thread pool to query
170  \return `true` if the thread pool is running a task, `false` otherwise
171  */
172  bool busy(const PoolIndex pool = DEFAULT_POOL);
173 
174  /**
175  Checks if a specific thread pool is doing great: rethrows exceptions occurred during tasks execution, if any.
176  \param pool The thread pool to query
177  */
178  void check(const PoolIndex pool = DEFAULT_POOL);
179 
180  /**
181  \returns maximum number of working threads per task in a given pool.
182  */
183  const ThreadIndex maxAllowedWorkerCount(const PoolIndex pool = DEFAULT_POOL) const;
184 
185  /**
186  Limits maximum number of threads (workers) when performing tasks in a given pool
187  \param maxValue Number limiting the worker count
188  \param pool The thread pool
189  \returns new maximum limit.
190  */
191  void limitWorkerCount(ThreadIndex maxValue, const PoolIndex pool = DEFAULT_POOL);
192 
193  /**
194  Installs new event listener
195  */
196  void setEventListener(EventListener* eventListener);
197 
198  /**
199  Returns current event listener (or NULL)
200  */
202 
203  /**
204  \return `true` if GPU was queried
205  */
206  bool isGpuQueried() const;
207 
208  /**
209  \return `true` if GPU was queried and ready to use
210  */
211  bool isGpuReady() const;
212 
213  /**
214  \brief Initializes GPU within a given Context if not yet (takes no effect if it already is).
215  GPU initialization may take some time and is done when a first task using GPU is being run. Warming up
216  the GPU is useful to avoid the app get stucked for some time when it launches its first task on GPU.
217  */
218  void warmUpGpu();
219 
220  /**
221  \brief Initializes the GPU if not yet and queries information about it.
222  \param[out] vendor GPU vendor string.
223  \param[out] renderer renderer string.
224  \return `true` if a GPU is found.
225  */
226  bool queryGpuInfo(std::string& vendor, std::string& renderer);
227 
228  /**
229  \internal
230  \return `true` if invoked from the context managing thread
231  */
232  bool isManagingThread() const;
233 
234  /**
235  \return GPU recycle bin to store GPU resources that can be freed only within a GPU-aware thread
236  */
238 
239  /**
240  Context comparaison operator
241  Two different instances of contexts are basically never identical; returning `true` only if the two point
242  to the same instance.
243  */
244  inline bool operator==(const Context& context) const {
245  return this == &context;
246  }
247  };
248 };
Task: an operation that can be executed by multiple threads in parallel.
Definition: parallelism.h:90
An event listener (bunch of callbacks)
Definition: context.h:72
virtual void taskFail(PoolIndex pool, AbstractTask &task, const std::exception &ex)=0
Called when a task fails.
virtual void gpuInitFail(PoolIndex pool, const std::exception &ex)=0
Called when GPU initialization failed.
virtual void threadCreated(PoolIndex pool)=0
Called when a new worker thread is created.
virtual void threadTerminating(PoolIndex pool)=0
Called when a worker thread finished.
virtual bool taskDone(PoolIndex pool, AbstractTask &task, bool aborted)=0
Called when a task is successfully finished.
Basic class: task and memory management, any kind of static data.
Definition: context.h:59
static const PoolIndex DEFAULT_POOL
Definition: context.h:67
const ThreadIndex maxAllowedWorkerCount(const PoolIndex pool=DEFAULT_POOL) const
Definition: context.cpp:276
GL::RecycleBin * recycleBin
stores GPU garbage: resources managed by GPU and might be freed in the managing thread only
Definition: context.h:64
bool isGpuReady() const
Definition: context.cpp:296
float performTask(AbstractTask &task, const PoolIndex pool=DEFAULT_POOL)
Performs a given task.
Definition: context.cpp:240
void wait(const PoolIndex pool=DEFAULT_POOL)
Blocks until all the submitted jobs are executed.
Definition: context.cpp:264
Job submitTask(AbstractTask &task, const PoolIndex pool=DEFAULT_POOL)
Adds a new task to the jobs queue.
Definition: context.cpp:248
bool operator==(const Context &context) const
Context comparaison operator Two different instances of contexts are basically never identical; retur...
Definition: context.h:244
bool abortJob(Job job, const PoolIndex pool=DEFAULT_POOL)
Aborts a given submitted job.
Definition: context.cpp:260
GL::RecycleBin * getGpuRecycleBin() const
Definition: context.cpp:340
bool isManagingThread() const
Definition: context.cpp:336
Job submitPersistentTask(AbstractTask &task, const PoolIndex pool=DEFAULT_POOL)
Adds a new persistent task to the jobs queue.
Definition: context.cpp:252
bool queryGpuInfo(std::string &vendor, std::string &renderer)
Initializes the GPU if not yet and queries information about it.
Definition: context.cpp:307
void check(const PoolIndex pool=DEFAULT_POOL)
Checks if a specific thread pool is doing great: rethrows exceptions occurred during tasks execution,...
Definition: context.cpp:272
EventListener * getEventListener() const
Returns current event listener (or NULL)
Definition: context.cpp:288
Context(const Context &)=delete
disabling copying constructor
bool busy(const PoolIndex pool=DEFAULT_POOL)
Queries whether a given thread pool is busy with a task.
Definition: context.cpp:268
void repeatTask(AbstractTask &task, bool abortCurrent, const PoolIndex pool=DEFAULT_POOL)
Ensures a given task executed at least once.
Definition: context.cpp:244
void warmUpGpu()
Initializes GPU within a given Context if not yet (takes no effect if it already is).
Definition: context.cpp:300
bool isGpuQueried() const
Definition: context.cpp:292
Impl * impl
Definition: context.h:62
void limitWorkerCount(ThreadIndex maxValue, const PoolIndex pool=DEFAULT_POOL)
Limits maximum number of threads (workers) when performing tasks in a given pool.
Definition: context.cpp:280
void setEventListener(EventListener *eventListener)
Installs new event listener.
Definition: context.cpp:284
void waitForJob(Job job, const PoolIndex pool=DEFAULT_POOL)
Waits until a given job finishes.
Definition: context.cpp:256
Stores references to GPU resources that will not be used anymore and needed to be recycled in a threa...
Definition: recycle_bin.h:34
Beatmup object base class
Definition: basic_types.h:67
Context class implementation (pimpl)
Definition: context.cpp:43
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
unsigned char PoolIndex
number of tread pools or a pool index
Definition: parallelism.h:67
int Job
Definition: parallelism.h:69
JNIEnv jlong jint jint job
Beatmup::SceneRenderer * renderer
Beatmup::NNets::InferenceTask * task