c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

task_manager.h
Go to the documentation of this file.
1 /* Copyright (C) 2012 and 2013 Chris Vine
2
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License, version 2.1, for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License, version 2.1, along with this library (see the file LGPL.TXT
19 which came with this source code package in the c++-gtk-utils
20 sub-directory); if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36
37 */
38
39 #ifndef CGU_TASK_MANAGER_H
40 #define CGU_TASK_MANAGER_H
41
42 #include <deque>
43 #include <utility> // for std::pair, std::move and std::forward
44 #include <exception> // for std::exception
45 #include <memory> // for std::unique_ptr
46 #include <type_traits> // for std::remove_reference, std::remove_const, std::enable_if,
47 // std::is_convertible and std::result_of
48
49 #include <c++-gtk-utils/callback.h>
50 #include <c++-gtk-utils/thread.h>
51 #include <c++-gtk-utils/mutex.h>
52 #include <c++-gtk-utils/async_queue.h>
53 #include <c++-gtk-utils/shared_ptr.h>
54 #include <c++-gtk-utils/async_result.h>
55 #include <c++-gtk-utils/emitter.h>
56 #include <c++-gtk-utils/cgu_config.h>
57
58 namespace Cgu {
59
60 namespace Thread {
61
62 struct TaskError: public std::exception {
63 virtual const char* what() const throw() {return "TaskError\n";}
64 };
65
66 /**
67 * @class Cgu::Thread::TaskManager task_manager.h c++-gtk-utils/task_manager.h
68 * @brief A thread-pool class for managing tasks in multi-threaded programs.
69 * @sa Cgu::Thread::Future Cgu::AsyncResult Cgu::AsyncQueueDispatch Cgu::Callback::post() Cgu::Thread::TaskManager::IncHandle Cgu::Thread::parallel_for_each() Cgu::Thread::parallel_transform()
70 *
71 * Cgu::Thread::Future operates on the principle of there being one
72 * worker thread per task. In some cases however, it may be better to
73 * have a limited pool of worker threads executing a larger number of
74 * tasks. This class implements this approach via a thread pool.
75 *
76 * One common approach for thread pools of this kind is to set the
77 * maximum number of threads to the number of cores, or some number
78 * less than the number of cores, available on the local machine. How
79 * that can be determined is system specific (on linux it can be
80 * obtained by, for example, counting the 'processor' fields in
81 * /proc/cpuinfo or by using sysconf with the glibc extension for
82 * _SC_NPROCESSORS_ONLN). From version 2.36, glib has a
83 * g_get_num_processors() function. From gcc-4.7, C++11's
84 * std::thread::hardware_concurrency() static member function is also
85 * available.
86 *
87 * The most general way of creating a new task is to call
88 * TaskManager::add_task() with a callable object (such as a lambda
89 * expression or the return value of std::bind) which returns void,
90 * although add_task() will also take a Callback::Callback object.
91 * Where the task needs to provide a result, two approaches can be
92 * adopted. First, the task callback can have a Cgu::AsyncResult
93 * object held by Cgu::SharedLockPtr (or by std::shared_ptr having a
94 * thread safe reference count) bound to it. Alternatively, a task
95 * can provide a result asynchronously to a glib main loop by calling
96 * Cgu::Callback::post() when it is ready to do so. The
97 * TaskManager::make_task_result(), TaskManager::make_task_when(),
98 * TaskManager::make_task_when_full() and
99 * TaskManager::make_task_compose() convenience wrapper methods are
100 * provided which will set this up for you (including constructing
101 * appropriate task callbacks). This would normally be done by
102 * passing one of those functions a callable object which returns a
103 * value, such as a lambda expression or the return value of
104 * std::bind. Tasks can add other tasks, enabling the composition of
105 * an arbitrary number of tasks to obtain a final result.
106 *
107 * Overloads of TaskManager::make_task_result(),
108 * TaskManager::make_task_when() and
109 * TaskManager::make_task_when_full() (but not
110 * TaskManager::make_task_compose()) also exist which take a function
111 * pointer (or an object reference and member function pointer) to a
112 * function which returns a value, with bound arguments, but these are
113 * deprecated in the 2.2 series of the library as they offer little
114 * advantage over using std::bind. (Although deprecated, there is no
115 * plan to remove these functions as they are there and they work -
116 * the deprecation is in effect guidance.) These deprecated functions
117 * can take up to three bound arguments in the case of a non-static
118 * member function, and four bound arguments in the case of any other
119 * function. In the case of a non-static member function, the
120 * referenced object whose member function is to be called must remain
121 * in existence until the task has completed. The target function
122 * passed by pointer (or member function pointer) can take a reference
123 * to const argument, as a copy of the object to be passed to the
124 * argument is taken to avoid dangling references, but it cannot take
125 * a reference to non-const argument.
126 *
127 * Copying of the return value of the target function or callable
128 * object represented by the task may take place when using
129 * TaskManager::make_task_result(), TaskManager::make_task_when(),
130 * TaskManager::make_task_when_full() and
131 * TaskManager::make_task_compose(). When a task completes, the
132 * return value will be stored, either in a Cgu::AsyncResult object
133 * (if TaskManager::make_task_result() is called) or for the purposes
134 * of executing the 'when' callback in a glib main loop (if
135 * TaskManager::make_task_when(), TaskManager::make_task_when_full()
136 * or TaskManager::make_task_compose() are called). This storage will
137 * therefore cause the return value type's assignment operator or copy
138 * constructor to be called once unless that type has a move
139 * assignment operator or move constructor, in which case a move
140 * operation will be made where possible. Note that a 'when' callback
141 * takes the stored return value by reference to const and so without
142 * any additional copying upon the 'when' callback being executed in
143 * the main loop.
144 *
145 * TaskManager objects do not provide thread cancellation. Thread
146 * cancellation is incompatible with the task-centred thread pool
147 * model. If task cancellation is wanted, use a Cgu::Thread::Future
148 * (or Cgu::Thread::Thread or Cgu::Thread::JoinableHandle) object
149 * instead, and have a dedicated thread for the cancelable task.
150 *
151 * If glib < 2.32 is installed, g_thread_init() must be called before
152 * any TaskManager objects are constructed, which in turn means that
153 * with glib < 2.32 TaskManager objects may not be constructed as
154 * static objects in global namespace (that is, before g_thread_init()
155 * has been called in the program).
156 *
157 * Any exceptions which propagate from a task will be consumed to
158 * protect the TaskManager object, and to detect whether this has
159 * happened there is a version of the TaskManager::add_task() method
160 * which takes a second argument comprising a 'fail' callback. If an
161 * exception propagates from the 'fail' callback that is also consumed
162 * and a g_critical() message issued.
163 * TaskManager::make_task_when_full() also provides for a 'fail'
164 * callback.
165 *
166 * Tasks can be aborted by throwing Cgu::Thread::Exit (as well as any
167 * other exception). Where a task is managed by a TaskManager object,
168 * throwing Cgu::Thread::Exit will only terminate the task and not the
169 * thread on which it is running (and will cause the 'fail' callback
170 * to be executed, if there is one).
171 *
172 * Any 'fail' callback passed to TaskManager::add_task() or
173 * TaskManager::make_task_when_full() must be fully bound. Whilst a
174 * task can pass error status to the 'fail' callback via shared data
175 * bound to both the task and the 'fail' callback (held by, say, a
176 * SharedLockPtr object), or a global error stack, 'fail' callbacks
177 * are generally best reserved for use with entirely unexpected
178 * exceptions, where the most reasonable course is to perform some
179 * orderly logging and shutdown. For handlable exceptions, in an
180 * asynchronous environment the best course is often to catch them and
181 * deal with them in the task itself and (where
182 * TaskManager::make_task_when_full(), TaskManager::make_task_when()
183 * or TaskManager::make_task_compose() is employed) return a value of
184 * the task function's return type indicating no result.
185 *
186 * TaskManager objects have no copy constructor or copy assignment
187 * operator, as copying them would have no obvious semantic meaning.
188 * Whilst swapping or moving TaskManager objects would be meaningful,
189 * this is not implemented either because it would require an
190 * additional internal lock to be thread safe, and the circumstances
191 * in which moving or swapping would be useful are limited. Where a
192 * move option is wanted, a TaskManager object can be constructed on
193 * free store and held by std::unique_ptr.
194 *
195 * Here is a compilable example of the calculator class referred to in
196 * the documentation on the AsyncResult but which uses a TaskManager
197 * object so that the calculator class can run more than one thread to
198 * service its calculations, using TaskManager::make_task_result():
199 *
200 * @code
201 * #include <vector>
202 * #include <numeric>
203 * #include <ostream>
204 * #include <iostream>
205 *
206 * #include <glib.h>
207 *
208 * #include <c++-gtk-utils/task_manager.h>
209 * #include <c++-gtk-utils/async_result.h>
210 * #include <c++-gtk-utils/shared_ptr.h>
211 *
212 * using namespace Cgu;
213 *
214 * class Calcs {
215 * Thread::TaskManager tm;
216 * public:
217 * SharedLockPtr<AsyncResult<double>> mean(const std::vector<double>& nums) {
218 * return tm.make_task_result([=]() -> double {
219 * if (nums.empty()) return 0.0;
220 * return std::accumulate(nums.begin(), nums.end(), 0.0)/nums.size();
221 * });
222 * }
223 *
224 * // ... other calculation methods here
225 * };
226 *
227 * int main () {
228 *
229 * g_thread_init(0);
230 * Calcs calcs;
231 * auto res1 = calcs.mean({1, 2, 8, 0});
232 * auto res2 = calcs.mean({101, 53.7, 87, 1.2});
233 *
234 * // ... do something else
235 * std::cout << res1->get() << std::endl;
236 * std::cout << res2->get() << std::endl;
237 *
238 * }
239 * @endcode
240 *
241 * Here is a reimplementation, using TaskManager::make_task_when(), of
242 * the example using a get_primes() function given in the
243 * documentation for Cgu::Thread::Future:
244 * @code
245 * std::vector<long> get_primes(int n); // calculates the first n primes
246 *
247 * // get the first 1,000 primes
248 * using namespace Cgu;
249 *
250 * Thread::TaskManager tm;
251 * tm.make_task_when([] (const std::vector<long>& result) {
252 * for (const auto& elt: result) {std::cout << elt << std::endl;}
253 * },
254 * 0, // default main loop context
255 * [] () {return get_primes(1,000);});
256 * @endcode
257 *
258 * Where a task running on a TaskManager object is to block, the
259 * TaskManager::IncHandle scoped handle class can be used to increment
260 * the maximum number of threads running on the object's thread pool
261 * temporarily while blocking takes place, so as to enable another
262 * thread to keep a core active. This can be useful where a task is
263 * to 'join' on another task when composing tasks. Here is a
264 * compilable example:
265 *
266 * @code
267 * #include <iostream>
268 * #include <ostream>
269 *
270 * #include <glib.h>
271 *
272 * #include <c++-gtk-utils/task_manager.h>
273 *
274 * using namespace Cgu;
275 *
276 * // simulate a blocking operation, say from a server, with g_usleep()
277 * int mult(int x, int y) {
278 * g_usleep(100000);
279 * return x * y;
280 * }
281 *
282 * int main(int argc, char* argv[]) {
283 *
284 * g_thread_init(0);
285 * Thread::TaskManager tm{1}; // only one core available unless blocking!
286 * GMainLoop* loop = g_main_loop_new(0, true);
287 *
288 * tm.make_task_when(
289 * [loop] (const int& res) {
290 * std::cout << res << std::endl;
291 * g_main_loop_quit(loop);
292 * },
293 * 0, // default main loop
294 * [&tm] () -> int {
295 * // this task multiplies 'a' by 2 and 'b' by 3, and adds the products
296 * int a = 10;
297 * int b = 12;
298 *
299 * // increment maximum thread count before launching sub-task and
300 * // then blocking
301 * Thread::TaskManager::IncHandle h{tm};
302 * // start a sub-task
303 * auto sub = tm.make_task_result([a, &tm] () -> int {
304 * // increment maximum thread count again before blocking in
305 * // this task (pretend that some other task in the program
306 * // may also want to run while both the parent task and this
307 * // task block on mult())
308 * Thread::TaskManager::IncHandle h{tm};
309 * return mult(a, 2);
310 * });
311 *
312 * int res = mult(b, 3)
313 * return sub->get() + res;
314 * }
315 * );
316 *
317 * g_main_loop_run(loop);
318 * }
319 * @endcode
320 */
321
322 // TODO: this is a work-around for gcc < 4.7, which has a bug which
323 // requires a function whose return value is determined by decltype,
324 // such as make_task_result(Func&&), to be inline. At a suitable
325 // API/ABI break when gcc requirements are updated, this should be
326 // moved to task_manager.tpp.
327 namespace TaskManagerHelper {
328
329 template <class Ret, class FType>
330 struct FunctorResultWrapper {
331 static void exec(FType& f,
332 const SharedLockPtr<AsyncResult<Ret>>& ret) {
333 ret->set(f());
334 }
335 static void do_fail(const SharedLockPtr<AsyncResult<Ret>>& ret) {
336 ret->set_error(); // won't throw
337 }
338 };
339
340 /*
341 * The FunctorResultExec class is a specialised class which is
342 * necessary because the 'functor member needs to be declared mutable
343 * so that it can bind to the reference to non-const argument of
344 * FunctorResultWrapper::exec(), and thus so that a mutable lambda can
345 * be executed by that function. Because it is so specialised, it is
346 * not suitable for inclusion in the generic interfaces provided in
347 * callback.h. (Except in this specialised usage, it can also be
348 * dangerous, as it allows a member of the callback object to be
349 * mutated: normally this would be undesirable.) An alternative would
350 * have been to put the 'functor' member in a wrapper struct like
351 * MemfunWhenWrapperArgs or FunWhenWrapperArgs, but if 'functor' were
352 * an lvalue that would mean it being copied twice. This is the most
353 * efficient implementation.
354 */
355 template <class Ret, class FType>
356 class FunctorResultExec: public Cgu::Callback::Callback {
357 mutable FType functor;
358 SharedLockPtr<AsyncResult<Ret>> ret;
359 public:
360 void dispatch() const {FunctorResultWrapper<Ret, FType>::exec(functor, ret);}
361 // we don't need to templatize 'ret_' for perfect forwarding - it is
362 // always passed as a lvalue
363 template <class FunctorArg>
364 FunctorResultExec(FunctorArg&& functor_,
365 const SharedLockPtr<AsyncResult<Ret>>& ret_): functor(std::forward<FunctorArg>(functor_)),
366 ret(ret_) {}
367 };
368
369 } // namespace TaskManagerHelper
370
371
372 class TaskManager {
373 public:
374 enum StopMode {wait_for_running, wait_for_all};
375 class IncHandle;
376 private:
377 typedef std::pair<std::unique_ptr<const Callback::Callback>,
378 std::unique_ptr<const Callback::Callback>> QueueItemType;
379
380 struct RefImpl; // reference counted implementation class
381 // it is fine holding RefImpl by plain pointer and not by
382 // IntrusivePtr: it is the only data member this class has, so it
383 // can safely manage that member in its own destructor and other
384 // methods
385 RefImpl* ref_impl;
386
387 void set_max_threads_impl(unsigned int max);
388 public:
389 /**
390 * This class cannot be copied. The copy constructor is deleted.
391 */
392 TaskManager(const TaskManager&) = delete;
393
394 /**
395 * This class cannot be copied. The assignment operator is deleted.
396 */
397 TaskManager& operator=(const TaskManager&) = delete;
398
399 /**
400 * Gets the maximum number of threads which the TaskManager object is
401 * currently set to run in the thread pool. This value is established
402 * initially by the 'max' argument passed to the TaskManager
403 * constructor and can subequently be changed by calling
404 * set_max_threads() or change_max_threads(). The default value is
405 * 8. This method will not throw and is thread safe. However, if a
406 * blocking task might use the TaskManager::IncHandle class (or
407 * increase and then decrease the number by hand by calling
408 * change_max_threads()), this method will not usually be of any
409 * particular value.
410 * @return The maximum number of threads.
411 *
412 * Since 2.0.12
413 */
414 unsigned int get_max_threads() const;
415
416 /**
417 * Gets the minimum number of threads which the TaskManager object
418 * will run in the thread pool (these threads will last until
419 * stop_all() is called or the TaskManager object is destroyed).
420 * This value is established by the 'min' argument passed to the
421 * TaskManager constructor and cannot subequently be changed. The
422 * default is 0. This method will not throw and is thread safe.
423 * @return The minimum number of threads.
424 *
425 * Since 2.0.12
426 */
427 unsigned int get_min_threads() const;
428
429 /**
430 * Gets the number of threads which the TaskManager object is
431 * currently running in the thread pool, including those blocking
432 * waiting for a task. This value could be greater than the number
433 * returned by get_max_threads() if set_max_threads() has recently
434 * been called with a value which is less than that number but not
435 * enough tasks have since completed to reduce the number of running
436 * threads to the new value set. This method will not throw and is
437 * thread safe.
438 * @return The number of threads running in the thread pool,
439 * including those blocking waiting for a task.
440 *
441 * Since 2.0.12
442 */
443 unsigned int get_used_threads() const;
444
445 /**
446 * Gets the number of tasks which the TaskManager object is at
447 * present either running in the thread pool or has queued for
448 * execution. This value will be less than the number returned by
449 * get_used_threads() if threads in the thread pool are currently
450 * waiting to receive tasks for execution. This method will not
451 * throw and is thread safe.
452 * @return The number of tasks either running or queued for
453 * execution.
454 *
455 * Since 2.0.12
456 */
457 unsigned int get_tasks() const;
458
459 /**
460 * @deprecated
461 *
462 * DEPRECATED. Use change_max_threads() instead. This method will
463 * interfere with the intended operation of the
464 * ThreadManager::IncHandle class if one task constructs a IncHandle
465 * object and another calls this method.
466 *
467 * Sets the maximum number of threads which the TaskManager object
468 * will currently run in the thread pool. If this is less than the
469 * current number of running threads, the number of threads actually
470 * running will only be reduced as tasks complete, or as idle
471 * timeouts expire. This method does nothing if stop_all() has
472 * previously been called. This method is thread safe.
473 * @param max The maximum number of threads which the TaskManager
474 * object will currently run in the thread pool. This method will
475 * not set the maximum value of threads to a value less than that
476 * returned by get_min_threads(), nor to a value less than 1.
477 * @exception std::bad_alloc If this call is passed a value for 'max'
478 * which increases the maximum number of threads from its previous
479 * setting and tasks are currently queued for execution, new threads
480 * will be started for the queued tasks, so this exception may be
481 * thrown on starting the new threads if memory is exhausted and the
482 * system throws in that case. (On systems with
483 * over-commit/lazy-commit combined with virtual memory (swap), it is
484 * rarely useful to check for memory exhaustion).
485 * @exception Cgu::Thread::TaskError If this call is passed a value
486 * for 'max' which increases the maximum number of threads from its
487 * previous setting and tasks are currently queued for execution, new
488 * threads will be started for the queued tasks, so this exception
489 * may be thrown on starting the new threads if a thread fails to
490 * start correctly (this would mean that memory is exhausted, the
491 * pthread thread limit has been reached or pthread has run out of
492 * other resources to start new threads).
493 *
494 * Since 2.0.12
495 */
496 void set_max_threads(unsigned int max);
497
498 /**
499 * This will increase, or if 'delta' is negative reduce, the maximum
500 * number of threads which the TaskManager object will currently run
501 * in the thread pool by the value of 'delta'. The purpose of this
502 * is to enable a task to increment the maximum thread number where
503 * it is about to enter a call which may block for some time, with a
504 * view to decrementing it later when it has finished making blocking
505 * calls, so as to enable another thread to keep a core active. If
506 * 'delta' is negative and results in a max_threads value of less
507 * than the current number of running threads, the number of threads
508 * actually running will only be reduced as tasks complete, or as
509 * idle timeouts expire. This method does nothing if stop_all() has
510 * previously been called. This method is thread safe. Since
511 * version 2.2.1, the scoped handle class TaskManager::IncHandle is
512 * available which calls this method.
513 * @param delta The change (positive or negative) to the maximum
514 * number of threads which the TaskManager object will currently run
515 * in the thread pool. This method will not set the maximum value of
516 * threads to a value less than that returned by get_min_threads(),
517 * nor to a value less than 1.
518 * @exception std::bad_alloc If this call is passed a positive value
519 * and tasks are currently queued for execution, a new thread or
520 * threads will be started for the queued tasks, so this exception
521 * may be thrown on starting a new thread if memory is exhausted and
522 * the system throws in that case. (On systems with
523 * over-commit/lazy-commit combined with virtual memory (swap), it is
524 * rarely useful to check for memory exhaustion).
525 * @exception Cgu::Thread::TaskError If this call is passed a
526 * positive value and tasks are currently queued for execution, a new
527 * thread or threads will be started for the queued tasks, so this
528 * exception may be thrown on starting a new thread if it fails to
529 * start correctly (this would mean that memory is exhausted, the
530 * pthread thread limit has been reached or pthread has run out of
531 * other resources to start new threads).
532 *
533 * Since 2.0.14
534 */
535 void change_max_threads(int delta);
536
537 /**
538 * Gets the length of time in milliseconds that threads greater in
539 * number than the minimum and not executing any tasks will remain in
540 * existence waiting for new tasks. This value is established
541 * initially by the 'idle' argument passed to the TaskManager
542 * constructor and can subequently be changed by calling
543 * set_idle_time(). The default value is 10000 (10 seconds). This
544 * method will not throw and is thread safe.
545 * @return The idle time in milliseconds.
546 *
547 * Since 2.0.12
548 */
549 unsigned int get_idle_time() const;
550
551 /**
552 * Sets the length of time in milliseconds that threads greater in
553 * number than the minimum and not executing any tasks will remain in
554 * existence waiting for new tasks. This will only have effect for
555 * threads in the pool which begin waiting for new tasks after this
556 * method is called. This method will not throw and is thread safe.
557 * @param idle The length of the idle time in milliseconds during
558 * which threads will remain waiting for new tasks.
559 *
560 * Since 2.0.12
561 */
562 void set_idle_time(unsigned int idle);
563
564 /**
565 * Gets the current blocking setting, which determines whether calls
566 * to stop_all() and the destructor will block waiting for all
567 * remaining tasks to complete. This value is established initially
568 * by the 'blocking' argument passed to the TaskManager constructor
569 * and can subequently be changed by calling set_blocking(). This
570 * method will not throw and is thread safe.
571 * @return The current blocking setting.
572 *
573 * Since 2.0.12
574 */
575 bool get_blocking() const;
576
577 /**
578 * Sets the current blocking setting, which determines whether calls
579 * to stop_all() and the destructor will block waiting for all
580 * remaining tasks to complete. This method cannot be called after
581 * stop_all() has been called (if that is attempted,
582 * Cgu::Thread::TaskError will be thrown). It is thread safe.
583 * @param blocking The new blocking setting.
584 * @exception Cgu::Thread::TaskError This exception will be thrown if
585 * stop_all() has previously been called.
586 *
587 * Since 2.0.12
588 */
589 void set_blocking(bool blocking);
590
591 /**
592 * Gets the current StopMode setting (either
593 * Cgu::Thread::TaskManager::wait_for_running or
594 * Cgu::Thread::TaskManager::wait_for_all) executed when running
595 * stop_all() or when the destructor is called. See the
596 * documentation on stop_all() for an explanation of the setting.
597 * This value is established initially by the 'mode' argument passed
598 * to the TaskManager constructor and can subequently be changed by
599 * calling set_stop_mode(). This method will not throw and is thread
600 * safe.
601 * @return The current StopMode setting.
602 *
603 * Since 2.0.12
604 */
605 StopMode get_stop_mode() const;
606
607 /**
608 * Sets the current StopMode setting (either
609 * Cgu::Thread::TaskManager::wait_for_running or
610 * Cgu::Thread::TaskManager::wait_for_all) executed when running
611 * stop_all() or when the destructor is called. See the
612 * documentation on stop_all() for an explanation of the setting.
613 * This method will not throw and is thread safe.
614 * @param mode The new StopMode setting.
615 *
616 * Since 2.0.12
617 */
618 void set_stop_mode(StopMode mode);
619
620 /**
621 * This will cause the TaskManager object to stop running tasks. The
622 * precise effect depends on the current StopMode and blocking
623 * settings. If StopMode is set to
624 * Cgu::Thread::TaskManager::wait_for_running, all queued tasks which
625 * are not yet running on a thread will be dispensed with, but any
626 * already running will be left to complete normally. If StopMode is
627 * set to Cgu::Thread::TaskManager::wait_for_all, both already
628 * running tasks and all tasks already queued will be permitted to
629 * execute and complete normally. If the blocking setting is set to
630 * true, this method will wait until all the tasks still to execute
631 * have finished before returning, and if false it will return
632 * straight away.
633 *
634 * After this method has been called, any attempt to add further
635 * tasks with the add_task() method will fail, and add_task() will
636 * throw Cgu::Thread::TaskError.
637 *
638 * This method is thread safe (any thread may call it) unless the
639 * blocking setting is true, in which case no task running on the
640 * TaskManager object may call this method.
641 * @exception std::bad_alloc This exception will be thrown if memory
642 * is exhausted and the system throws in that case. (On systems with
643 * over-commit/lazy-commit combined with virtual memory (swap), it is
644 * rarely useful to check for memory exhaustion).
645 * @exception Cgu::Thread::TaskError This exception will be thrown if
646 * stop_all() has previously been called, unless that previous call
647 * threw std::bad_alloc: if std::bad_alloc is thrown, this method may
648 * be called again to stop all threads, once the memory deficiency is
649 * dealt with, but no other methods of the TaskManager object should
650 * be called.
651 *
652 * Since 2.0.12
653 */
654 void stop_all();
655
656 /**
657 * This method adds a new task. If one or more threads in the pool
658 * are currently blocking and waiting for a task, then the task will
659 * begin executing immediately in one of the threads. If not, and
660 * the value returned by get_used_threads() is less than the value
661 * returned by get_max_threads(), a new thread will start and the
662 * task will execute immediately in the new thread. Otherwise, the
663 * task will be queued for execution as soon as a thread becomes
664 * available. Tasks will be executed in the order in which they are
665 * added to the ThreadManager object. This method is thread safe
666 * (any thread may call it, including any task running on the
667 * TaskManager object).
668 *
669 * A task may terminate itself prematurely by throwing
670 * Cgu::Thread::Exit. In addition, the implementation of TaskManager
671 * will consume any other exception escaping from the task callback
672 * and safely terminate the task concerned in order to protect the
673 * integrity of the TaskManager object. Where detecting any of these
674 * outcomes is important (usually it won't be), the two argument
675 * version of this method is available so that a 'fail' callback can
676 * be executed in these circumstances.
677 *
678 * @param task A callback representing the new task, as constructed
679 * by the Callback::lambda(), Callback::make() or
680 * Callback::make_ref() factory functions. Ownership is taken of
681 * this callback, and it will be disposed of when it has been
682 * finished with. If an exception propagates from the task, the
683 * exception will be consumed and (if the thrown object's type is not
684 * Cgu::Thread::Exit) a g_critical() warning will be issued. The
685 * destructors of any bound arguments in the callback must not throw.
686 * @exception std::bad_alloc This exception will be thrown if memory
687 * is exhausted and the system throws in that case. (On systems with
688 * over-commit/lazy-commit combined with virtual memory (swap), it is
689 * rarely useful to check for memory exhaustion). If this exception
690 * is thrown, the task will not start and the 'task' callback will be
691 * disposed of.
692 * @exception Cgu::Thread::TaskError This exception will be thrown if
693 * stop_all() has previously been called. It will also be thrown if
694 * is_error() would return true because this class's internal thread
695 * pool loop implementation has thrown std::bad_alloc, or a thread
696 * has failed to start correctly. (On systems with
697 * over-commit/lazy-commit combined with virtual memory (swap), it is
698 * rarely useful to check for memory exhaustion, but there may be
699 * some specialized cases where the return value of is_error() is
700 * useful.) If this exception is thrown, the task will not start and
701 * the 'task' callback will be disposed of.
702 *
703 * Since 2.0.12
704 */
705 void add_task(const Callback::Callback* task) {
706 add_task(std::unique_ptr<const Callback::Callback>(task),
707 std::unique_ptr<const Callback::Callback>());
708 }
709
710 /**
711 * This method adds a new task. If one or more threads in the pool
712 * are currently blocking and waiting for a task, then the task will
713 * begin executing immediately in one of the threads. If not, and
714 * the value returned by get_used_threads() is less than the value
715 * returned by get_max_threads(), a new thread will start and the
716 * task will execute immediately in the new thread. Otherwise, the
717 * task will be queued for execution as soon as a thread becomes
718 * available. Tasks will be executed in the order in which they are
719 * added to the ThreadManager object. This method is thread safe
720 * (any thread may call it, including any task running on the
721 * TaskManager object).
722 *
723 * A task may terminate itself prematurely by throwing
724 * Cgu::Thread::Exit. In addition, the implementation of TaskManager
725 * will consume any other exception escaping from the task callback
726 * and safely terminate the task concerned in order to protect the
727 * integrity of the TaskManager object. Where detecting any of these
728 * outcomes is important (usually it won't be), a callback can be
729 * passed to the 'fail' argument which will execute if, and only if,
730 * either Cgu::Thread::Exit is thrown or some other exception has
731 * propagated from the task. This 'fail' callback is different from
732 * the 'fail' callback of Cgu::Thread::Future objects (programming
733 * for many tasks to a lesser number of threads requires different
734 * approaches from programming for one thread per task), and it
735 * executes in the task thread rather than executing in a glib main
736 * loop (however, the 'fail' callback can of course call
737 * Cgu::Callback::post() to execute another callback in a main loop,
738 * if that is what is wanted).
739 *
740 * @param task A callback representing the new task, as constructed
741 * by the Callback::lambda(), Callback::make() or
742 * Callback::make_ref() factory functions. If an exception
743 * propagates from the task, the exception will be consumed and the
744 * 'fail' callback will execute.
745 * @param fail A callback (as constructed by the Callback::lambda(),
746 * Callback::make() or Callback::make_ref() factory functions) which
747 * will be executed if the function or callable object executed by
748 * the 'task' callback exits by throwing Thread::Exit or some other
749 * exception. If an exception propagates from the 'fail' callback,
750 * this will be consumed to protect the TaskManager object, and a
751 * g_critical() warning will be issued.
752 * @exception std::bad_alloc This exception will be thrown if memory
753 * is exhausted and the system throws in that case. (On systems with
754 * over-commit/lazy-commit combined with virtual memory (swap), it is
755 * rarely useful to check for memory exhaustion). If this exception
756 * is thrown, the task will not start (which also means that the
757 * 'fail' callback will not execute).
758 * @exception Cgu::Thread::TaskError This exception will be thrown if
759 * stop_all() has previously been called. It will also be thrown if
760 * is_error() would return true because this class's internal thread
761 * pool loop implementation has thrown std::bad_alloc, or a thread
762 * has failed to start correctly. (On systems with
763 * over-commit/lazy-commit combined with virtual memory (swap), it is
764 * rarely useful to check for memory exhaustion, but there may be
765 * some specialized cases where the return value of is_error() is
766 * useful.) If this exception is thrown, the task will not start
767 * (which also means that the 'fail' callback will not execute).
768 *
769 * Since 2.0.12
770 */
771 void add_task(std::unique_ptr<const Callback::Callback> task,
772 std::unique_ptr<const Callback::Callback> fail);
773
774 /**
775 * This method adds a new task. If one or more threads in the pool
776 * are currently blocking and waiting for a task, then the task will
777 * begin executing immediately in one of the threads. If not, and
778 * the value returned by get_used_threads() is less than the value
779 * returned by get_max_threads(), a new thread will start and the
780 * task will execute immediately in the new thread. Otherwise, the
781 * task will be queued for execution as soon as a thread becomes
782 * available. Tasks will be executed in the order in which they are
783 * added to the ThreadManager object. This method is thread safe
784 * (any thread may call it, including any task running on the
785 * TaskManager object).
786 *
787 * A task may terminate itself prematurely by throwing
788 * Cgu::Thread::Exit. In addition, the implementation of TaskManager
789 * will consume any other exception escaping from the task callback
790 * and safely terminate the task concerned in order to protect the
791 * integrity of the TaskManager object. Where detecting any of these
792 * outcomes is important (usually it won't be), the two argument
793 * version of this method is available so that a 'fail' callback can
794 * be executed in these circumstances.
795 *
796 * @param task A callable object representing the new task, such as
797 * formed by a lambda expression or the result of std::bind. It must
798 * be fully bound (that is, it must take no arguments when called).
799 * If an exception propagates from the task, the exception will be
800 * consumed and (if the thrown object's type is not
801 * Cgu::Thread::Exit) a g_critical() warning will be issued. The
802 * destructors of any bound values must not throw.
803 * @exception std::bad_alloc This exception will be thrown if memory
804 * is exhausted and the system throws in that case. (On systems with
805 * over-commit/lazy-commit combined with virtual memory (swap), it is
806 * rarely useful to check for memory exhaustion). If this exception
807 * is thrown, the task will not start.
808 * @exception Cgu::Thread::TaskError This exception will be thrown if
809 * stop_all() has previously been called. It will also be thrown if
810 * is_error() would return true because this class's internal thread
811 * pool loop implementation has thrown std::bad_alloc, or a thread
812 * has failed to start correctly. (On systems with
813 * over-commit/lazy-commit combined with virtual memory (swap), it is
814 * rarely useful to check for memory exhaustion, but there may be
815 * some specialized cases where the return value of is_error() is
816 * useful.) If this exception is thrown, the task will not start.
817 * @note An exception might also be thrown if the copy or move
818 * constructor of the callable object throws. If such an exception
819 * is thrown, the task will not start.
820 *
821 * Since 2.1.0
822 */
823 // we need to use enable_if so that where this function is passed a
824 // pointer to non-const Callback::Callback, or some other
825 // convertible pointer, this templated overload is dropped from the
826 // overload set, in order to support the Callback::Callback
827 // overloads of this function. This overload calls into the version
828 // of this function taking a pointer to const Callback::Callback in
829 // order to perform type erasure.
830 template <class Task,
831 class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<Task>::type,
832 const Callback::Callback*>::value>::type>
833 void add_task(Task&& task) {
834 add_task(std::unique_ptr<const Callback::Callback>(Callback::lambda<>(std::forward<Task>(task))),
835 std::unique_ptr<const Callback::Callback>());
836 }
837
838 /**
839 * This method adds a new task. If one or more threads in the pool
840 * are currently blocking and waiting for a task, then the task will
841 * begin executing immediately in one of the threads. If not, and
842 * the value returned by get_used_threads() is less than the value
843 * returned by get_max_threads(), a new thread will start and the
844 * task will execute immediately in the new thread. Otherwise, the
845 * task will be queued for execution as soon as a thread becomes
846 * available. Tasks will be executed in the order in which they are
847 * added to the ThreadManager object. This method is thread safe
848 * (any thread may call it, including any task running on the
849 * TaskManager object).
850 *
851 * A task may terminate itself prematurely by throwing
852 * Cgu::Thread::Exit. In addition, the implementation of TaskManager
853 * will consume any other exception escaping from the task callback
854 * and safely terminate the task concerned in order to protect the
855 * integrity of the TaskManager object. Where detecting any of these
856 * outcomes is important (usually it won't be), a callback can be
857 * passed to the 'fail' argument which will execute if, and only if,
858 * either Cgu::Thread::Exit is thrown or some other exception has
859 * propagated from the task. This 'fail' callback is different from
860 * the 'fail' callback of Cgu::Thread::Future objects (programming
861 * for many tasks to a lesser number of threads requires different
862 * approaches from programming for one thread per task), and it
863 * executes in the task thread rather than executing in a glib main
864 * loop (however, the 'fail' callback can of course call
865 * Cgu::Callback::post() to execute another callback in a main loop,
866 * if that is what is wanted).
867 *
868 * @param task A callable object representing the new task, such as
869 * formed by a lambda expression or the result of std::bind. It must
870 * be fully bound (that is, it must take no arguments when called).
871 * The destructors of any bound values must not throw. If an exception
872 * propagates from the task, the exception will be consumed and the
873 * 'fail' callback will execute.
874 * @param fail A callable object (such as formed by a lambda
875 * expression or the result of std::bind) which will be executed if
876 * the callable object represented by the 'task' callback exits by
877 * throwing Thread::Exit or some other exception. It must be fully
878 * bound (that is, it must take no arguments when called). The
879 * destructors of any bound values must not throw. If an exception
880 * propagates from the 'fail' callback, this will be consumed to
881 * protect the TaskManager object, and a g_critical() warning will be
882 * issued.
883 * @exception std::bad_alloc This exception will be thrown if memory
884 * is exhausted and the system throws in that case. (On systems with
885 * over-commit/lazy-commit combined with virtual memory (swap), it is
886 * rarely useful to check for memory exhaustion). If this exception
887 * is thrown, the task will not start (which also means that the
888 * 'fail' callback will not execute).
889 * @exception Cgu::Thread::TaskError This exception will be thrown if
890 * stop_all() has previously been called. It will also be thrown if
891 * is_error() would return true because this class's internal thread
892 * pool loop implementation has thrown std::bad_alloc, or a thread
893 * has failed to start correctly. (On systems with
894 * over-commit/lazy-commit combined with virtual memory (swap), it is
895 * rarely useful to check for memory exhaustion, but there may be
896 * some specialized cases where the return value of is_error() is
897 * useful.) If this exception is thrown, the task will not start
898 * (which also means that the 'fail' callback will not execute).
899 * @note An exception might also be thrown if the copy or move
900 * constructor of the 'task' or 'fail' callable objects throws. If
901 * such an exception is thrown, the task will not start (which also
902 * means that the 'fail' callback will not execute)
903 *
904 * Since 2.1.0
905 */
906 // we need to use enable_if so that where this function is passed
907 // unique_ptr's holding non-const Callback::Callback objects, or
908 // some other convertible object, this templated overload is dropped
909 // from the overload set, in order to support the unique_ptr
910 // overloads of this function. This overload calls into the version
911 // of this function taking Callback objects by unique_ptr in order
912 // to perform type erasure.
913 template <class Task, class Fail,
914 class = typename std::enable_if<!std::is_convertible<Task, std::unique_ptr<const Callback::Callback>>::value
915 && !std::is_convertible<Fail, std::unique_ptr<const Callback::Callback>>::value>::type>
916 void add_task(Task&& task, Fail&& fail) {
917 std::unique_ptr<const Callback::Callback> task_cb(
918 Callback::lambda<>(std::forward<Task>(task))
919 );
920 std::unique_ptr<const Callback::Callback> fail_cb(
921 Callback::lambda<>(std::forward<Fail>(fail))
922 );
923 add_task(std::move(task_cb), std::move(fail_cb));
924 }
925
926 /**
927 * This will return true if a thread required by the thread pool has
928 * failed to start correctly because of memory exhaustion or because
929 * pthread has run out of other resources to start new threads, or
930 * because an internal operation has thrown std::bad_alloc. (On
931 * systems with over-commit/lazy-commit combined with virtual memory
932 * (swap), it is rarely useful to check for memory exhaustion, and
933 * even more so where glib is used, as that terminates a program if
934 * memory cannot be obtained from the operating system, but there may
935 * be some specialized cases where the return value of this method is
936 * useful - this class does not use any glib functions which might
937 * cause such termination.) This method will not throw and is thread
938 * safe.
939 *
940 * Since 2.0.12
941 */
942 bool is_error() const;
943
944 /**
945 * @deprecated
946 *
947 * DEPRECATED. Use the versions of make_task_result() which take
948 * callable objects.
949 *
950 * This is a wrapper which will take a member function pointer to a
951 * member function which returns a value, together with arguments,
952 * and constructs a TaskManager task which will execute that function
953 * by calling add_task() with an appropriate callback object, and
954 * returns a Cgu::AsyncResult object (held by Cgu::SharedLockPtr)
955 * which will provide the value that the function returns. It is
956 * thread safe (any thread may call this method, including another
957 * task running on the TaskManager object). Apart from the absence
958 * of a 'one thread per task' model, this method therefore provides a
959 * similar interface to the one provided by Cgu::Thread::Future. See
960 * the documentation on add_task() for further information about how
961 * task execution works.
962 *
963 * This method can take up to three bound arguments for the target
964 * member function.
965 *
966 * If the function passed to this method exits by throwing
967 * Thread::Exit or some other exception, then the exception will be
968 * consumed and the returned Cgu::AsyncResult object's get() method
969 * will unblock and its get_error() method will return -1.
970 *
971 * @param t The object whose member function passed to this method is
972 * to execute as a task.
973 * @param func The member function to be executed as a task.
974 * @param args The arguments to be passed to that member function.
975 * @exception std::bad_alloc This exception will be thrown if memory
976 * is exhausted and the system throws in that case. (On systems with
977 * over-commit/lazy-commit combined with virtual memory (swap), it is
978 * rarely useful to check for memory exhaustion). If this exception
979 * is thrown, the task will not start.
980 * @exception Cgu::Thread::TaskError This exception will be thrown if
981 * stop_all() has previously been called. It will also be thrown if
982 * is_error() would return true because this class's internal thread
983 * pool loop implementation has thrown std::bad_alloc, or a thread
984 * has failed to start correctly. (On systems with
985 * over-commit/lazy-commit combined with virtual memory (swap), it is
986 * rarely useful to check for memory exhaustion, but there may be
987 * some specialized cases where the return value of is_error() is
988 * useful.) If this exception is thrown, the task will not start.
989 * @note This method will also throw if the copy or move constructor
990 * of a bound argument throws. If such an exception is thrown, the
991 * task will not start.
992 *
993 * Since 2.0.13
994 */
995
996 template <class Ret, class... Params, class... Args, class T>
997 Cgu::SharedLockPtr<Cgu::AsyncResult<Ret>> make_task_result(T& t,
998 Ret (T::*func)(Params...),
999 Args&&... args);
1000
1001 /**
1002 * @deprecated
1003 *
1004 * DEPRECATED. Use the versions of make_task_when_full() which take
1005 * callable objects.
1006 *
1007 * This is a wrapper which will take a member function pointer to a
1008 * member function which returns a value, together with arguments,
1009 * and constructs a TaskManager task which will execute that function
1010 * by calling add_task() with an appropriate callback object, and
1011 * causes the 'when' callback passed as an argument to this method to
1012 * be executed by a glib main loop if and when the task finishes
1013 * correctly - the 'when' callback is passed the member function's
1014 * return value when it is invoked. It is thread safe (any thread
1015 * may call this method, including another task running on the
1016 * TaskManager object). Apart from the absence of a 'one thread per
1017 * task' model, this method therefore provides a similar interface to
1018 * the one provided by Cgu::Thread::Future. See the documentation on
1019 * add_task() for further information about how task execution works.
1020 *
1021 * This method can take up to three bound arguments for the target
1022 * member function.
1023 *
1024 * Note that unlike add_task(), but like the 'fail' callback of
1025 * Cgu::Thread::Future objects, if a fail callback is provided to
1026 * this method and it executes, it will execute in the glib main loop
1027 * whose GMainContext object is passed to the 'context' argument of
1028 * this method.
1029 *
1030 * Note also that if releasers are provided for the 'when' or 'fail'
1031 * callbacks, these are passed by pointer and not by reference (this
1032 * is so that a NULL pointer can indicate that no releaser is to be
1033 * provided). If provided, a releaser will enable automatic
1034 * disconnection of the 'when' or 'fail' callback, if the object
1035 * having the callback function as a member is destroyed. For this to
1036 * be race free, the lifetime of that object must be controlled by
1037 * the thread in whose main loop the 'when' or 'fail' callback will
1038 * execute.
1039 *
1040 * The make_task_when() method is similar to this method but provides
1041 * an abbreviated set of paramaters suitable for most cases. This
1042 * method is for use where releasers or a 'fail' callback are
1043 * required.
1044 *
1045 * @param when A callback which will be executed if and when the
1046 * function passed to this method finishes correctly. The callback is
1047 * passed that function's return value when it is invoked. If an
1048 * exception propagates from the 'when' callback, this will be
1049 * consumed and a g_critical() warning will be issued. The callback
1050 * will execute in the glib main loop whose GMainContext object is
1051 * passed to the 'context' argument of this method.
1052 * @param when_releaser A pointer to a Releaser object for automatic
1053 * disconnection of the 'when' callback before it executes in a main
1054 * loop (mainly relevant if the callback represents a non-static
1055 * member function of an object which may be destroyed before the
1056 * callback executes). A value of 0/NULL/nullptr indicates no
1057 * releaser.
1058 * @param fail A callback which will be executed if the 'when'
1059 * callback does not execute. This would happen if the function
1060 * passed to this method exits by throwing Thread::Exit or some other
1061 * exception or the copy constructor of a non-reference argument of
1062 * that function throws, or if the 'when' callback does not execute
1063 * because the internal implementation of this wrapper throws
1064 * std::bad_alloc (which will not happen if the library has been
1065 * installed using the –with-glib-memory-slices-no-compat
1066 * configuration option: instead glib will terminate the program if
1067 * it is unable to obtain memory from the operating system). If an
1068 * exception propagates from the 'fail' callback, this will be
1069 * consumed and a g_critical() warning will be issued. The callback
1070 * will execute in the glib main loop whose GMainContext object is
1071 * passed to the 'context' argument of this method. An empty
1072 * std::unique_ptr object indicates no 'fail' callback.
1073 * @param fail_releaser A pointer to a Releaser object for automatic
1074 * disconnection of the 'fail' callback before it executes in a main
1075 * loop (mainly relevant if the callback represents a non-static
1076 * member function of an object which may be destroyed before the
1077 * callback executes). A value of 0/NULL/nullptr indicates no
1078 * releaser.
1079 * @param priority The priority to be given in the main loop to the
1080 * 'when' callback or any 'fail' callback. In ascending order of
1081 * priorities, priorities are G_PRIORITY_LOW,
1082 * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1083 * and G_PRIORITY_HIGH. This determines the order in which the
1084 * callback will appear in the event list in the main loop, not the
1085 * priority which the OS will adopt.
1086 * @param context The glib main context of the main loop in which the
1087 * 'when' callback or any 'fail' callback is to be executed. A value
1088 * 0/NULL/nullptr will cause the callback to be executed in the main
1089 * program loop.
1090 * @param t The object whose member function passed to this method is
1091 * to execute as a task.
1092 * @param func The member function to be executed as a task. If an
1093 * exception propagates from the task, the exception will be consumed
1094 * and the 'fail' callback will execute.
1095 * @param args The arguments to be passed to that member function.
1096 * @exception std::bad_alloc This exception will be thrown if memory
1097 * is exhausted and the system throws in that case. (On systems with
1098 * over-commit/lazy-commit combined with virtual memory (swap), it is
1099 * rarely useful to check for memory exhaustion). If this exception
1100 * is thrown, the task will not start (which also means that the
1101 * 'when' and 'fail' callbacks will not execute).
1102 * @exception Cgu::Thread::TaskError This exception will be thrown if
1103 * stop_all() has previously been called. It will also be thrown if
1104 * is_error() would return true because this class's internal thread
1105 * pool loop implementation has thrown std::bad_alloc, or a thread
1106 * has failed to start correctly. (On systems with
1107 * over-commit/lazy-commit combined with virtual memory (swap), it is
1108 * rarely useful to check for memory exhaustion, but there may be
1109 * some specialized cases where the return value of is_error() is
1110 * useful.) If this exception is thrown, the task will not start
1111 * (which also means that the 'when' and 'fail' callbacks will not
1112 * execute).
1113 * @note 1. This method will also throw if the copy or move
1114 * constructor of a bound argument throws. If such an exception is
1115 * thrown, the task will not start (which also means that the 'when'
1116 * and 'fail' callbacks will not execute).
1117 * @note 2. If a 'when_releaser' or a 'fail_releaser' argument is
1118 * provided, it is in theory possible (if memory is exhausted and the
1119 * system throws in that case) that an internal SafeEmitterArg object
1120 * will throw std::bad_alloc when emitting/executing the 'when' or
1121 * 'fail' callback in the glib main loop, with the result that the
1122 * relevant callback will not execute (instead the exception will be
1123 * consumed and a g_critical() warning will be issued). This is
1124 * rarely of any relevance because glib will abort the program if it
1125 * is itself unable to obtain memory from the operating system.
1126 * However, where it is relevant, design the program so that it is
1127 * not necessary to provide a releaser object.
1128 *
1129 * Since 2.0.13
1130 */
1131 template <class Ret, class... Params, class... Args, class T>
1132 void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1133 Cgu::Releaser* when_releaser,
1134 std::unique_ptr<const Cgu::Callback::Callback> fail,
1135 Cgu::Releaser* fail_releaser,
1136 gint priority,
1137 GMainContext* context,
1138 T& t,
1139 Ret (T::*func)(Params...),
1140 Args&&... args);
1141
1142 /**
1143 * @deprecated
1144 *
1145 * DEPRECATED. Use the versions of make_task_when() which take
1146 * callable objects.
1147 *
1148 * This is an abbreviated version of make_task_when_full(), which is
1149 * for use when it is known that the member function passed to this
1150 * method, and the copy constructors of any non-reference bound
1151 * arguments passed to it, do not throw, and the user is not
1152 * interested in std::bad_alloc and does not need a Cgu::Releaser
1153 * object for the 'when' callback (which is likely to cover the
1154 * majority of uses, particularly when composing tasks using glib
1155 * because glib terminates the program if it is unable to obtain
1156 * memory).
1157 *
1158 * This method can take up to three bound arguments for the target
1159 * member function.
1160 *
1161 * Like make_task_when_full(), this method is a wrapper which will
1162 * take a member function pointer to a member function which returns
1163 * a value, together with arguments, and constructs a TaskManager
1164 * task which will execute that function by calling add_task() with
1165 * an appropriate callback object, and causes the 'when' callback
1166 * passed as an argument to this method to be executed by a glib main
1167 * loop if and when the task finishes correctly - the 'when' callback
1168 * is passed the member function's return value when it is invoked.
1169 * It is thread safe (any thread may call this method, including
1170 * another task running on the TaskManager object). Apart from the
1171 * absence of a 'one thread per task' model, this method therefore
1172 * provides a similar interface to the one provided by
1173 * Cgu::Thread::Future. See the documentation on add_task() for
1174 * further information about how task execution works.
1175 *
1176 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
1177 * in the main loop.
1178 *
1179 * @param when A callback which will be executed if and when the
1180 * function passed to this method finishes correctly. The callback is
1181 * passed that function's return value when it is invoked. If an
1182 * exception propagates from the 'when' callback, this will be
1183 * consumed and a g_critical() warning will be issued. The callback
1184 * will execute in the glib main loop whose GMainContext object is
1185 * passed to the 'context' argument of this method.
1186 * @param context The glib main context of the main loop in which the
1187 * 'when' callback is to be executed. A value 0/NULL/nullptr will
1188 * cause the callback to be executed in the main program loop.
1189 * @param t The object whose member function passed to this method is
1190 * to execute as a task.
1191 * @param func The member function to be executed as a task. If an
1192 * exception propagates from the task, the exception will be consumed
1193 * and (if the thrown object's type is not Cgu::Thread::Exit) a
1194 * g_critical() warning will be issued.
1195 * @param args The arguments to be passed to that member function.
1196 * @exception std::bad_alloc This exception will be thrown if memory
1197 * is exhausted and the system throws in that case. (On systems with
1198 * over-commit/lazy-commit combined with virtual memory (swap), it is
1199 * rarely useful to check for memory exhaustion). If this exception
1200 * is thrown, the task will not start (which also means that the
1201 * 'when' callback will not execute).
1202 * @exception Cgu::Thread::TaskError This exception will be thrown if
1203 * stop_all() has previously been called. It will also be thrown if
1204 * is_error() would return true because this class's internal thread
1205 * pool loop implementation has thrown std::bad_alloc, or a thread
1206 * has failed to start correctly. (On systems with
1207 * over-commit/lazy-commit combined with virtual memory (swap), it is
1208 * rarely useful to check for memory exhaustion, but there may be
1209 * some specialized cases where the return value of is_error() is
1210 * useful.) If this exception is thrown, the task will not start
1211 * (which also means that the 'when' callback will not execute).
1212 * @note This method will also throw if the copy or move constructor
1213 * of a bound argument throws. If such an exception is thrown, the
1214 * task will not start (which also means that the 'when' callback
1215 * will not execute).
1216 *
1217 * Since 2.0.13
1218 */
1219 template <class Ret, class... Params, class... Args, class T>
1220 void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1221 GMainContext* context,
1222 T& t,
1223 Ret (T::*func)(Params...),
1224 Args&&... args) {
1225 static_assert(sizeof...(Args) < 4,
1226 "No greater than three bound arguments can be passed to "
1227 "TaskManager::make_task_when() taking a member function.");
1228
1229 make_task_when_full(std::move(when),
1230 0,
1231 std::unique_ptr<const Cgu::Callback::Callback>(),
1232 0,
1233 G_PRIORITY_DEFAULT,
1234 context,
1235 t,
1236 func,
1237 std::forward<Args>(args)...);
1238 }
1239
1240 /**
1241 * @deprecated
1242 *
1243 * DEPRECATED. Use the versions of make_task_result() which take
1244 * callable objects.
1245 *
1246 * This is a wrapper which will take a member function pointer to a
1247 * member function which returns a value, together with arguments,
1248 * and constructs a TaskManager task which will execute that function
1249 * by calling add_task() with an appropriate callback object, and
1250 * returns a Cgu::AsyncResult object (held by Cgu::SharedLockPtr)
1251 * which will provide the value that the function returns. It is
1252 * thread safe (any thread may call this method, including another
1253 * task running on the TaskManager object). Apart from the absence
1254 * of a 'one thread per task' model, this method therefore provides a
1255 * similar interface to the one provided by Cgu::Thread::Future. See
1256 * the documentation on add_task() for further information about how
1257 * task execution works.
1258 *
1259 * This method can take up to three bound arguments for the target
1260 * member function.
1261 *
1262 * If the function passed to this method exits by throwing
1263 * Thread::Exit or some other exception, then the exception will be
1264 * consumed and the returned Cgu::AsyncResult object's get() method
1265 * will unblock and its get_error() method will return -1.
1266 *
1267 * @param t The object whose member function passed to this method is
1268 * to execute as a task.
1269 * @param func The member function to be executed as a task.
1270 * @param args The arguments to be passed to that member function.
1271 * @exception std::bad_alloc This exception will be thrown if memory
1272 * is exhausted and the system throws in that case. (On systems with
1273 * over-commit/lazy-commit combined with virtual memory (swap), it is
1274 * rarely useful to check for memory exhaustion). If this exception
1275 * is thrown, the task will not start.
1276 * @exception Cgu::Thread::TaskError This exception will be thrown if
1277 * stop_all() has previously been called. It will also be thrown if
1278 * is_error() would return true because this class's internal thread
1279 * pool loop implementation has thrown std::bad_alloc, or a thread
1280 * has failed to start correctly. (On systems with
1281 * over-commit/lazy-commit combined with virtual memory (swap), it is
1282 * rarely useful to check for memory exhaustion, but there may be
1283 * some specialized cases where the return value of is_error() is
1284 * useful.) If this exception is thrown, the task will not start.
1285 * @note This method will also throw if the copy or move constructor
1286 * of a bound argument throws. If such an exception is thrown, the
1287 * task will not start.
1288 *
1289 * Since 2.0.13
1290 */
1291
1292 template <class Ret, class... Params, class... Args, class T>
1293 Cgu::SharedLockPtr<Cgu::AsyncResult<Ret>> make_task_result(const T& t,
1294 Ret (T::*func)(Params...) const,
1295 Args&&... args);
1296
1297 /**
1298 * @deprecated
1299 *
1300 * DEPRECATED. Use the versions of make_task_when_full() which take
1301 * callable objects.
1302 *
1303 * This is a wrapper which will take a member function pointer to a
1304 * member function which returns a value, together with arguments,
1305 * and constructs a TaskManager task which will execute that function
1306 * by calling add_task() with an appropriate callback object, and
1307 * causes the 'when' callback passed as an argument to this method to
1308 * be executed by a glib main loop if and when the task finishes
1309 * correctly - the 'when' callback is passed the member function's
1310 * return value when it is invoked. It is thread safe (any thread
1311 * may call this method, including another task running on the
1312 * TaskManager object). Apart from the absence of a 'one thread per
1313 * task' model, this method therefore provides a similar interface to
1314 * the one provided by Cgu::Thread::Future. See the documentation on
1315 * add_task() for further information about how task execution works.
1316 *
1317 * This method can take up to three bound arguments for the target
1318 * member function.
1319 *
1320 * Note that unlike add_task(), but like the 'fail' callback of
1321 * Cgu::Thread::Future objects, if a fail callback is provided to
1322 * this method and it executes, it will execute in the glib main loop
1323 * whose GMainContext object is passed to the 'context' argument of
1324 * this method.
1325 *
1326 * Note also that if releasers are provided for the 'when' or 'fail'
1327 * callbacks, these are passed by pointer and not by reference (this
1328 * is so that a NULL pointer can indicate that no releaser is to be
1329 * provided). If provided, a releaser will enable automatic
1330 * disconnection of the 'when' or 'fail' callback, if the object
1331 * having the callback function as a member is destroyed. For this to
1332 * be race free, the lifetime of that object must be controlled by
1333 * the thread in whose main loop the 'when' or 'fail' callback will
1334 * execute.
1335 *
1336 * The make_task_when() method is similar to this method but provides
1337 * an abbreviated set of paramaters suitable for most cases. This
1338 * method is for use where releasers or a 'fail' callback are
1339 * required.
1340 *
1341 * @param when A callback which will be executed if and when the
1342 * function passed to this method finishes correctly. The callback is
1343 * passed that function's return value when it is invoked. If an
1344 * exception propagates from the 'when' callback, this will be
1345 * consumed and a g_critical() warning will be issued. The callback
1346 * will execute in the glib main loop whose GMainContext object is
1347 * passed to the 'context' argument of this method.
1348 * @param when_releaser A pointer to a Releaser object for automatic
1349 * disconnection of the 'when' callback before it executes in a main
1350 * loop (mainly relevant if the callback represents a non-static
1351 * member function of an object which may be destroyed before the
1352 * callback executes). A value of 0/NULL/nullptr indicates no
1353 * releaser.
1354 * @param fail A callback which will be executed if the 'when'
1355 * callback does not execute. This would happen if the function
1356 * passed to this method exits by throwing Thread::Exit or some other
1357 * exception or the copy constructor of a non-reference argument of
1358 * that function throws, or if the 'when' callback does not execute
1359 * because the internal implementation of this wrapper throws
1360 * std::bad_alloc (which will not happen if the library has been
1361 * installed using the –with-glib-memory-slices-no-compat
1362 * configuration option: instead glib will terminate the program if
1363 * it is unable to obtain memory from the operating system). If an
1364 * exception propagates from the 'fail' callback, this will be
1365 * consumed and a g_critical() warning will be issued. The callback
1366 * will execute in the glib main loop whose GMainContext object is
1367 * passed to the 'context' argument of this method. An empty
1368 * std::unique_ptr object indicates no 'fail' callback.
1369 * @param fail_releaser A pointer to a Releaser object for automatic
1370 * disconnection of the 'fail' callback before it executes in a main
1371 * loop (mainly relevant if the callback represents a non-static
1372 * member function of an object which may be destroyed before the
1373 * callback executes). A value of 0/NULL/nullptr indicates no
1374 * releaser.
1375 * @param priority The priority to be given in the main loop to the
1376 * 'when' callback or any 'fail' callback. In ascending order of
1377 * priorities, priorities are G_PRIORITY_LOW,
1378 * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1379 * and G_PRIORITY_HIGH. This determines the order in which the
1380 * callback will appear in the event list in the main loop, not the
1381 * priority which the OS will adopt.
1382 * @param context The glib main context of the main loop in which the
1383 * 'when' callback or any 'fail' callback is to be executed. A value
1384 * 0/NULL/nullptr will cause the callback to be executed in the main
1385 * program loop.
1386 * @param t The object whose member function passed to this method is
1387 * to execute as a task.
1388 * @param func The member function to be executed as a task. If an
1389 * exception propagates from the task, the exception will be consumed
1390 * and the 'fail' callback will execute.
1391 * @param args The arguments to be passed to that member function.
1392 * @exception std::bad_alloc This exception will be thrown if memory
1393 * is exhausted and the system throws in that case. (On systems with
1394 * over-commit/lazy-commit combined with virtual memory (swap), it is
1395 * rarely useful to check for memory exhaustion). If this exception
1396 * is thrown, the task will not start (which also means that the
1397 * 'when' and 'fail' callbacks will not execute).
1398 * @exception Cgu::Thread::TaskError This exception will be thrown if
1399 * stop_all() has previously been called. It will also be thrown if
1400 * is_error() would return true because this class's internal thread
1401 * pool loop implementation has thrown std::bad_alloc, or a thread
1402 * has failed to start correctly. (On systems with
1403 * over-commit/lazy-commit combined with virtual memory (swap), it is
1404 * rarely useful to check for memory exhaustion, but there may be
1405 * some specialized cases where the return value of is_error() is
1406 * useful.) If this exception is thrown, the task will not start
1407 * (which also means that the 'when' and 'fail' callbacks will not
1408 * execute).
1409 * @note 1. This method will also throw if the copy or move
1410 * constructor of a bound argument throws. If such an exception is
1411 * thrown, the task will not start (which also means that the 'when'
1412 * and 'fail' callbacks will not execute).
1413 * @note 2. If a 'when_releaser' or a 'fail_releaser' argument is
1414 * provided, it is in theory possible (if memory is exhausted and the
1415 * system throws in that case) that an internal SafeEmitterArg object
1416 * will throw std::bad_alloc when emitting/executing the 'when' or
1417 * 'fail' callback in the glib main loop, with the result that the
1418 * relevant callback will not execute (instead the exception will be
1419 * consumed and a g_critical() warning will be issued). This is
1420 * rarely of any relevance because glib will abort the program if it
1421 * is itself unable to obtain memory from the operating system.
1422 * However, where it is relevant, design the program so that it is
1423 * not necessary to provide a releaser object.
1424 *
1425 * Since 2.0.13
1426 */
1427 template <class Ret, class... Params, class... Args, class T>
1428 void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1429 Cgu::Releaser* when_releaser,
1430 std::unique_ptr<const Cgu::Callback::Callback> fail,
1431 Cgu::Releaser* fail_releaser,
1432 gint priority,
1433 GMainContext* context,
1434 const T& t,
1435 Ret (T::*func)(Params...) const,
1436 Args&&... args);
1437
1438 /**
1439 * @deprecated
1440 *
1441 * DEPRECATED. Use the versions of make_task_when() which take
1442 * callable objects.
1443 *
1444 * This is an abbreviated version of make_task_when_full(), which is
1445 * for use when it is known that the member function passed to this
1446 * method, and the copy constructors of any non-reference bound
1447 * arguments passed to it, do not throw, and the user is not
1448 * interested in std::bad_alloc and does not need a Cgu::Releaser
1449 * object for the 'when' callback (which is likely to cover the
1450 * majority of uses, particularly when composing tasks using glib
1451 * because glib terminates the program if it is unable to obtain
1452 * memory).
1453 *
1454 * This method can take up to three bound arguments for the target
1455 * member function.
1456 *
1457 * Like make_task_when_full(), this method is a wrapper which will
1458 * take a member function pointer to a member function which returns
1459 * a value, together with arguments, and constructs a TaskManager
1460 * task which will execute that function by calling add_task() with
1461 * an appropriate callback object, and causes the 'when' callback
1462 * passed as an argument to this method to be executed by a glib main
1463 * loop if and when the task finishes correctly - the 'when' callback
1464 * is passed the member function's return value when it is invoked.
1465 * It is thread safe (any thread may call this method, including
1466 * another task running on the TaskManager object). Apart from the
1467 * absence of a 'one thread per task' model, this method therefore
1468 * provides a similar interface to the one provided by
1469 * Cgu::Thread::Future. See the documentation on add_task() for
1470 * further information about how task execution works.
1471 *
1472 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
1473 * in the main loop.
1474 *
1475 * @param when A callback which will be executed if and when the
1476 * function passed to this method finishes correctly. The callback is
1477 * passed that function's return value when it is invoked. If an
1478 * exception propagates from the 'when' callback, this will be
1479 * consumed and a g_critical() warning will be issued. The callback
1480 * will execute in the glib main loop whose GMainContext object is
1481 * passed to the 'context' argument of this method.
1482 * @param context The glib main context of the main loop in which the
1483 * 'when' callback is to be executed. A value 0/NULL/nullptr will
1484 * cause the callback to be executed in the main program loop.
1485 * @param t The object whose member function passed to this method is
1486 * to execute as a task.
1487 * @param func The member function to be executed as a task. If an
1488 * exception propagates from the task, the exception will be consumed
1489 * and (if the thrown object's type is not Cgu::Thread::Exit) a
1490 * g_critical() warning will be issued.
1491 * @param args The arguments to be passed to that member function.
1492 * @exception std::bad_alloc This exception will be thrown if memory
1493 * is exhausted and the system throws in that case. (On systems with
1494 * over-commit/lazy-commit combined with virtual memory (swap), it is
1495 * rarely useful to check for memory exhaustion). If this exception
1496 * is thrown, the task will not start (which also means that the
1497 * 'when' callback will not execute).
1498 * @exception Cgu::Thread::TaskError This exception will be thrown if
1499 * stop_all() has previously been called. It will also be thrown if
1500 * is_error() would return true because this class's internal thread
1501 * pool loop implementation has thrown std::bad_alloc, or a thread
1502 * has failed to start correctly. (On systems with
1503 * over-commit/lazy-commit combined with virtual memory (swap), it is
1504 * rarely useful to check for memory exhaustion, but there may be
1505 * some specialized cases where the return value of is_error() is
1506 * useful.) If this exception is thrown, the task will not start
1507 * (which also means that the 'when' callback will not execute).
1508 * @note This method will also throw if the copy or move constructor
1509 * of a bound argument throws. If such an exception is thrown, the
1510 * task will not start (which also means that the 'when' callback
1511 * will not execute).
1512 *
1513 * Since 2.0.13
1514 */
1515 template <class Ret, class... Params, class... Args, class T>
1516 void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1517 GMainContext* context,
1518 const T& t,
1519 Ret (T::*func)(Params...) const,
1520 Args&&... args) {
1521 static_assert(sizeof...(Args) < 4,
1522 "No greater than three bound arguments can be passed to "
1523 "TaskManager::make_task_when() taking a member function.");
1524
1525 make_task_when_full(std::move(when),
1526 0,
1527 std::unique_ptr<const Cgu::Callback::Callback>(),
1528 0,
1529 G_PRIORITY_DEFAULT,
1530 context,
1531 t,
1532 func,
1533 std::forward<Args>(args)...);
1534 }
1535
1536 /**
1537 * @deprecated
1538 *
1539 * DEPRECATED. Use the versions of make_task_result() which take
1540 * callable objects.
1541 *
1542 * This is a wrapper which will take a pointer to a function which
1543 * returns a value, together with arguments, and constructs a
1544 * TaskManager task which will execute that function by calling
1545 * add_task() with an appropriate callback object, and returns a
1546 * Cgu::AsyncResult object (held by Cgu::SharedLockPtr) which will
1547 * provide the value that the function returns. It is thread safe
1548 * (any thread may call this method, including another task running
1549 * on the TaskManager object). Apart from the absence of a 'one
1550 * thread per task' model, this method therefore provides a similar
1551 * interface to the one provided by Cgu::Thread::Future. See the
1552 * documentation on add_task() for further information about how task
1553 * execution works.
1554 *
1555 * This method can take up to four bound arguments for the target
1556 * function.
1557 *
1558 * If the function passed to this method exits by throwing
1559 * Thread::Exit or some other exception, then the exception will be
1560 * consumed and the returned Cgu::AsyncResult object's get() method
1561 * will unblock and its get_error() method will return -1.
1562 *
1563 * @param func The function to be executed as a task.
1564 * @param args The arguments to be passed to that function.
1565 * @exception std::bad_alloc This exception will be thrown if memory
1566 * is exhausted and the system throws in that case. (On systems with
1567 * over-commit/lazy-commit combined with virtual memory (swap), it is
1568 * rarely useful to check for memory exhaustion). If this exception
1569 * is thrown, the task will not start.
1570 * @exception Cgu::Thread::TaskError This exception will be thrown if
1571 * stop_all() has previously been called. It will also be thrown if
1572 * is_error() would return true because this class's internal thread
1573 * pool loop implementation has thrown std::bad_alloc, or a thread
1574 * has failed to start correctly. (On systems with
1575 * over-commit/lazy-commit combined with virtual memory (swap), it is
1576 * rarely useful to check for memory exhaustion, but there may be
1577 * some specialized cases where the return value of is_error() is
1578 * useful.) If this exception is thrown, the task will not start.
1579 * @note This method will also throw if the copy or move constructor
1580 * of a bound argument throws. If such an exception is thrown, the
1581 * task will not start.
1582 *
1583 * Since 2.0.13
1584 */
1585 template <class Ret, class... Params, class... Args>
1586 Cgu::SharedLockPtr<Cgu::AsyncResult<Ret>> make_task_result(Ret (*func)(Params...),
1587 Args&&... args);
1588
1589 /**
1590 * @deprecated
1591 *
1592 * DEPRECATED. Use the versions of make_task_when_full() which take
1593 * callable objects.
1594 *
1595 * This is a wrapper which will take a pointer to a function which
1596 * returns a value, together with arguments, and constructs a
1597 * TaskManager task which will execute that function by calling
1598 * add_task() with an appropriate callback object, and causes the
1599 * 'when' callback passed as an argument to this method to be
1600 * executed by a glib main loop if and when the task finishes
1601 * correctly - the 'when' callback is passed the function's return
1602 * value when it is invoked. It is thread safe (any thread may call
1603 * this method, including another task running on the TaskManager
1604 * object). Apart from the absence of a 'one thread per task' model,
1605 * this method therefore provides a similar interface to the one
1606 * provided by Cgu::Thread::Future. See the documentation on
1607 * add_task() for further information about how task execution works.
1608 *
1609 * This method can take up to four bound arguments for the target
1610 * function.
1611 *
1612 * Note that unlike add_task(), but like the 'fail' callback of
1613 * Cgu::Thread::Future objects, if a fail callback is provided to
1614 * this method and it executes, it will execute in the glib main loop
1615 * whose GMainContext object is passed to the 'context' argument of
1616 * this method.
1617 *
1618 * Note also that if releasers are provided for the 'when' or 'fail'
1619 * callbacks, these are passed by pointer and not by reference (this
1620 * is so that a NULL pointer can indicate that no releaser is to be
1621 * provided). If provided, a releaser will enable automatic
1622 * disconnection of the 'when' or 'fail' callback, if the object of
1623 * which the releaser is a member is destroyed. For this to be race
1624 * free, the lifetime of that object must be controlled by the thread
1625 * in whose main loop the 'when' or 'fail' callback will execute.
1626 *
1627 * The make_task_when() method is similar to this method but provides
1628 * an abbreviated set of paramaters suitable for most cases. This
1629 * method is for use where releasers or a 'fail' callback are
1630 * required.
1631 *
1632 * @param when A callback which will be executed if and when the
1633 * function passed to this method finishes correctly. The callback is
1634 * passed that function's return value when it is invoked. If an
1635 * exception propagates from the 'when' callback, this will be
1636 * consumed and a g_critical() warning will be issued. The callback
1637 * will execute in the glib main loop whose GMainContext object is
1638 * passed to the 'context' argument of this method.
1639 * @param when_releaser A pointer to a Releaser object for automatic
1640 * disconnection of the 'when' callback before it executes in a main
1641 * loop (mainly relevant if the callback represents a non-static
1642 * member function of an object which may be destroyed before the
1643 * callback executes). A value of 0/NULL/nullptr indicates no
1644 * releaser.
1645 * @param fail A callback which will be executed if the 'when'
1646 * callback does not execute. This would happen if the function
1647 * passed to this method exits by throwing Thread::Exit or some other
1648 * exception or the copy constructor of a non-reference argument of
1649 * that function throws, or if the 'when' callback does not execute
1650 * because the internal implementation of this wrapper throws
1651 * std::bad_alloc (which will not happen if the library has been
1652 * installed using the –with-glib-memory-slices-no-compat
1653 * configuration option: instead glib will terminate the program if
1654 * it is unable to obtain memory from the operating system). If an
1655 * exception propagates from the 'fail' callback, this will be
1656 * consumed and a g_critical() warning will be issued. The callback
1657 * will execute in the glib main loop whose GMainContext object is
1658 * passed to the 'context' argument of this method. An empty
1659 * std::unique_ptr object indicates no 'fail' callback.
1660 * @param fail_releaser A pointer to a Releaser object for automatic
1661 * disconnection of the 'fail' callback before it executes in a main
1662 * loop (mainly relevant if the callback represents a non-static
1663 * member function of an object which may be destroyed before the
1664 * callback executes). A value of 0/NULL/nullptr indicates no
1665 * releaser.
1666 * @param priority The priority to be given in the main loop to the
1667 * 'when' callback or any 'fail' callback. In ascending order of
1668 * priorities, priorities are G_PRIORITY_LOW,
1669 * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1670 * and G_PRIORITY_HIGH. This determines the order in which the
1671 * callback will appear in the event list in the main loop, not the
1672 * priority which the OS will adopt.
1673 * @param context The glib main context of the main loop in which the
1674 * 'when' callback or any 'fail' callback is to be executed. A value
1675 * 0/NULL/nullptr will cause the callback to be executed in the main
1676 * program loop.
1677 * @param func The function to be executed as a task. If an
1678 * exception propagates from the task, the exception will be consumed
1679 * and the 'fail' callback will execute.
1680 * @param args The arguments to be passed to that function.
1681 * @exception std::bad_alloc This exception will be thrown if memory
1682 * is exhausted and the system throws in that case. (On systems with
1683 * over-commit/lazy-commit combined with virtual memory (swap), it is
1684 * rarely useful to check for memory exhaustion). If this exception
1685 * is thrown, the task will not start (which also means that the
1686 * 'when' and 'fail' callbacks will not execute).
1687 * @exception Cgu::Thread::TaskError This exception will be thrown if
1688 * stop_all() has previously been called. It will also be thrown if
1689 * is_error() would return true because this class's internal thread
1690 * pool loop implementation has thrown std::bad_alloc, or a thread
1691 * has failed to start correctly. (On systems with
1692 * over-commit/lazy-commit combined with virtual memory (swap), it is
1693 * rarely useful to check for memory exhaustion, but there may be
1694 * some specialized cases where the return value of is_error() is
1695 * useful.) If this exception is thrown, the task will not start
1696 * (which also means that the 'when' and 'fail' callbacks will not
1697 * execute).
1698 * @note 1. This method will also throw if the copy or move
1699 * constructor of a bound argument throws. If such an exception is
1700 * thrown, the task will not start (which also means that the 'when'
1701 * and 'fail' callbacks will not execute).
1702 * @note 2. If a 'when_releaser' or a 'fail_releaser' argument is
1703 * provided, it is in theory possible (if memory is exhausted and the
1704 * system throws in that case) that an internal SafeEmitterArg object
1705 * will throw std::bad_alloc when emitting/executing the 'when' or
1706 * 'fail' callback in the glib main loop, with the result that the
1707 * relevant callback will not execute (instead the exception will be
1708 * consumed and a g_critical() warning will be issued). This is
1709 * rarely of any relevance because glib will abort the program if it
1710 * is itself unable to obtain memory from the operating system.
1711 * However, where it is relevant, design the program so that it is
1712 * not necessary to provide a releaser object.
1713 *
1714 * Since 2.0.13
1715 */
1716 template <class Ret, class... Params, class... Args>
1717 void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1718 Cgu::Releaser* when_releaser,
1719 std::unique_ptr<const Cgu::Callback::Callback> fail,
1720 Cgu::Releaser* fail_releaser,
1721 gint priority,
1722 GMainContext* context,
1723 Ret (*func)(Params...),
1724 Args&&... args);
1725
1726 /**
1727 * @deprecated
1728 *
1729 * DEPRECATED. Use the versions of make_task_when() which take
1730 * callable objects.
1731 *
1732 * This is an abbreviated version of make_task_when_full(), which is
1733 * for use when it is known that the function passed to this method,
1734 * and the copy constructors of any non-reference bound arguments
1735 * passed to it, do not throw, and the user is not interested in
1736 * std::bad_alloc and does not need a Cgu::Releaser object for the
1737 * 'when' callback (which is likely to cover the majority of uses,
1738 * particularly when composing tasks using glib because glib
1739 * terminates the program if it is unable to obtain memory).
1740 *
1741 * This method can take up to four bound arguments for the target
1742 * function.
1743 *
1744 * Like make_task_when_full(), this method is a wrapper which will
1745 * take a pointer to a function which returns a value, together with
1746 * arguments, and constructs a TaskManager task which will execute
1747 * that function by calling add_task() with an appropriate callback
1748 * object, and causes the 'when' callback passed as an argument to
1749 * this method to be executed by a glib main loop if and when the
1750 * task finishes correctly - the 'when' callback is passed the
1751 * function's return value when it is invoked. It is thread safe
1752 * (any thread may call this method, including another task running
1753 * on the TaskManager object). Apart from the absence of a 'one
1754 * thread per task' model, this method therefore provides a similar
1755 * interface to the one provided by Cgu::Thread::Future. See the
1756 * documentation on add_task() for further information about how task
1757 * execution works.
1758 *
1759 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
1760 * in the main loop.
1761 *
1762 * @param when A callback which will be executed if and when the
1763 * function passed to this method finishes correctly. The callback is
1764 * passed that function's return value when it is invoked. If an
1765 * exception propagates from the 'when' callback, this will be
1766 * consumed and a g_critical() warning will be issued. The callback
1767 * will execute in the glib main loop whose GMainContext object is
1768 * passed to the 'context' argument of this method.
1769 * @param context The glib main context of the main loop in which the
1770 * 'when' callback is to be executed. A value 0/NULL/nullptr will
1771 * cause the callback to be executed in the main program loop.
1772 * @param func The function to be executed as a task. If an
1773 * exception propagates from the task, the exception will be consumed
1774 * and (if the thrown object's type is not Cgu::Thread::Exit) a
1775 * g_critical() warning will be issued.
1776 * @param args The arguments to be passed to that function.
1777 * @exception std::bad_alloc This exception will be thrown if memory
1778 * is exhausted and the system throws in that case. (On systems with
1779 * over-commit/lazy-commit combined with virtual memory (swap), it is
1780 * rarely useful to check for memory exhaustion). If this exception
1781 * is thrown, the task will not start (which also means that the
1782 * 'when' callback will not execute).
1783 * @exception Cgu::Thread::TaskError This exception will be thrown if
1784 * stop_all() has previously been called. It will also be thrown if
1785 * is_error() would return true because this class's internal thread
1786 * pool loop implementation has thrown std::bad_alloc, or a thread
1787 * has failed to start correctly. (On systems with
1788 * over-commit/lazy-commit combined with virtual memory (swap), it is
1789 * rarely useful to check for memory exhaustion, but there may be
1790 * some specialized cases where the return value of is_error() is
1791 * useful.) If this exception is thrown, the task will not start
1792 * (which also means that the 'when' callback will not execute).
1793 * @note This method will also throw if the copy or move constructor
1794 * of a bound argument throws. If such an exception is thrown, the
1795 * task will not start (which also means that the 'when' callback
1796 * will not execute).
1797 *
1798 * Since 2.0.13
1799 */
1800 template <class Ret, class... Params, class... Args>
1801 void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1802 GMainContext* context,
1803 Ret (*func)(Params...),
1804 Args&&... args) {
1805 static_assert(sizeof...(Args) < 5,
1806 "No greater than four bound arguments can be passed to "
1807 "TaskManager::make_task_when() taking a function.");
1808
1809 make_task_when_full(std::move(when),
1810 0,
1811 std::unique_ptr<const Cgu::Callback::Callback>(),
1812 0,
1813 G_PRIORITY_DEFAULT,
1814 context,
1815 func,
1816 std::forward<Args>(args)...);
1817 }
1818
1819 /**
1820 * This is a wrapper which will take a callable object (such as a
1821 * std::function object, a lambda or the return value of std::bind)
1822 * representing a function which returns a value, and constructs a
1823 * TaskManager task which will execute that function by calling
1824 * add_task() with an appropriate callback object, and returns a
1825 * Cgu::AsyncResult object (held by Cgu::SharedLockPtr) which will
1826 * provide the value that the function returns. It is thread safe
1827 * (any thread may call this method, including another task running
1828 * on the TaskManager object). Apart from the absence of a 'one
1829 * thread per task' model, this method therefore provides a similar
1830 * interface to the one provided by Cgu::Thread::Future. See the
1831 * documentation on add_task() for further information about how task
1832 * execution works.
1833 *
1834 * If the callable object passed to this method exits by throwing
1835 * Thread::Exit or some other exception, then the exception will be
1836 * consumed and the returned Cgu::AsyncResult object's get() method
1837 * will unblock and its get_error() method will return -1.
1838 *
1839 * @param f The callable object to be executed as a task, such as
1840 * formed by a lambda expression or the result of std::bind. It
1841 * should return a value (it cannot return void).
1842 * @exception std::bad_alloc This exception will be thrown if memory
1843 * is exhausted and the system throws in that case. (On systems with
1844 * over-commit/lazy-commit combined with virtual memory (swap), it is
1845 * rarely useful to check for memory exhaustion). If this exception
1846 * is thrown, the task will not start.
1847 * @exception Cgu::Thread::TaskError This exception will be thrown if
1848 * stop_all() has previously been called. It will also be thrown if
1849 * is_error() would return true because this class's internal thread
1850 * pool loop implementation has thrown std::bad_alloc, or a thread
1851 * has failed to start correctly. (On systems with
1852 * over-commit/lazy-commit combined with virtual memory (swap), it is
1853 * rarely useful to check for memory exhaustion, but there may be
1854 * some specialized cases where the return value of is_error() is
1855 * useful.) If this exception is thrown, the task will not start.
1856 * @note 1. This method will also throw if the copy or move
1857 * constructor of the callable object throws. If such an exception
1858 * is thrown, the task will not start.
1859 * @note 2. If the callable object passed as an argument has both
1860 * const and non-const operator()() methods, the non-const version
1861 * will be called even if the callable object passed is a const
1862 * object.
1863 *
1864 * Since 2.0.14
1865 */
1866 // we don't need this version of make_task_result() for syntactic
1867 // reasons - the version taking a single template parameter will do
1868 // by itself syntactically because it can use decltype. However, we
1869 // include this version in order to be API compatible with
1870 // c++-gtk-utils < 2.0.14, which required the return type to be
1871 // specified when this method is passed something other than a
1872 // std::function object. SFINAE will take care of the rest, except
1873 // with a corner case where all of the following apply: (i) a
1874 // function object is passed whose operator()() method returns a
1875 // copy of the function object (or another function object of the
1876 // same type), (ii) the function object is passed to this method as
1877 // a rvalue and not a lvalue, and (iii) the user specifically states
1878 // the return type when instantiating this template function. This
1879 // would give rise to an ambiguity, but its happening is extremely
1880 // unlikely, and cannot happen with a lambda or the return value of
1881 // std::bind, because those types are only known to the compiler,
1882 // and cannot happen with other objects if the user lets template
1883 // deduction take its course.
1884 template <class Ret, class Func>
1885 Cgu::SharedLockPtr<Cgu::AsyncResult<Ret>> make_task_result(Func&& f);
1886
1887 // we don't want to document this function: it provides the type
1888 // deduction of the return value of the passed functor (it deals
1889 // with cases where this is not specified expressly).
1890 #ifndef DOXYGEN_PARSING
1891 template <class Func>
1892 auto make_task_result(Func&& f) -> Cgu::SharedLockPtr<Cgu::AsyncResult<decltype(f())>> {
1893
1894 // TODO: this is a work-around for gcc < 4.7, which has a bug
1895 // which requires a function whose return value is determined by
1896 // decltype, such as make_task_result(Func&&), to be inline. At a
1897 // suitable API/ABI break when gcc requirements are updated, this
1898 // should be moved to task_manager.tpp.
1899
1900 // there are two types related to the functor to be executed by
1901 // the task. 'Func' is the transient type provided by argument
1902 // deduction for forwarding, and will vary depending on whether
1903 // the functor object is a lvalue (which will deduce it as a
1904 // reference type) or rvalue (which will not). 'FType' is the
1905 // type to be held by the callback object generated in this
1906 // function, and is never a reference type. It is also never
1907 // const, because the FType member is marked mutable in the
1908 // callback object so that it can execute mutable lambdas (or
1909 // other functors with a non-const operator()() method).
1910 typedef typename std::remove_const<typename std::remove_reference<Func>::type>::type FType;
1911 typedef decltype(f()) Ret;
1912 typedef std::unique_ptr<const Callback::Callback> CbPtr;
1913
1914 SharedLockPtr<AsyncResult<Ret>> ret{new AsyncResult<Ret>};
1915 CbPtr exec_cb(new TaskManagerHelper::FunctorResultExec<Ret, FType>(std::forward<Func>(f), ret));
1916 CbPtr do_fail_cb(Callback::make_ref(&TaskManagerHelper::FunctorResultWrapper<Ret, FType>::do_fail,
1917 ret));
1918 add_task(std::move(exec_cb), std::move(do_fail_cb));
1919
1920 return ret;
1921 }
1922 #endif
1923
1924 /**
1925 * This is a wrapper which will take a callable object (such as a
1926 * std::function object, a lambda or the return value of std::bind)
1927 * representing a function which returns a value, and constructs a
1928 * TaskManager task which will execute that function by calling
1929 * add_task() with an appropriate callback object, and causes the
1930 * 'when' callback passed as an argument to this method to be
1931 * executed by a glib main loop if and when the task finishes
1932 * correctly - the 'when' callback is passed the function's return
1933 * value when it is invoked. It is thread safe (any thread may call
1934 * this method, including another task running on the TaskManager
1935 * object). Apart from the absence of a 'one thread per task' model,
1936 * this method therefore provides a similar interface to the one
1937 * provided by Cgu::Thread::Future. See the documentation on
1938 * add_task() for further information about how task execution works.
1939 *
1940 * Note that unlike add_task(), but like the 'fail' callback of
1941 * Cgu::Thread::Future objects, if a fail callback is provided to
1942 * this method and it executes, it will execute in the glib main loop
1943 * whose GMainContext object is passed to the 'context' argument of
1944 * this method.
1945 *
1946 * Note also that if releasers are provided for the 'when' or 'fail'
1947 * callbacks, these are passed by pointer and not by reference (this
1948 * is so that a NULL pointer can indicate that no releaser is to be
1949 * provided). If provided, a releaser will enable automatic
1950 * disconnection of the 'when' or 'fail' callback, if the object of
1951 * which the releaser is a member is destroyed. For this to be race
1952 * free, the lifetime of that object must be controlled by the thread
1953 * in whose main loop the 'when' or 'fail' callback will execute.
1954 *
1955 * The make_task_when() method is similar to this method but provides
1956 * an abbreviated set of parameters suitable for most cases. This
1957 * method is for use where releasers or a 'fail' callback are
1958 * required.
1959 *
1960 * @param when A callback which will be executed if and when the
1961 * callable object passed as 'func' to this method finishes
1962 * correctly. The callback is passed that object's return value when
1963 * it is invoked. If an exception propagates from the 'when'
1964 * callback, this will be consumed and a g_critical() warning will be
1965 * issued. The callback will execute in the glib main loop whose
1966 * GMainContext object is passed to the 'context' argument of this
1967 * method.
1968 * @param when_releaser A pointer to a Releaser object for automatic
1969 * disconnection of the 'when' callback before it executes in a main
1970 * loop (mainly relevant if the callback represents a non-static
1971 * member function of an object which may be destroyed before the
1972 * callback executes). A value of 0/NULL/nullptr indicates no
1973 * releaser.
1974 * @param fail A callback which will be executed if the 'when'
1975 * callback does not execute. This would happen if the callable
1976 * object passed as 'func' to this method exits by throwing
1977 * Thread::Exit or some other exception (or if that object represents
1978 * a function taking a non-reference argument whose copy constructor
1979 * throws), or if the 'when' callback does not execute because the
1980 * internal implementation of this wrapper throws std::bad_alloc
1981 * (which will not happen if the library has been installed using the
1982 * –with-glib-memory-slices-no-compat configuration option: instead
1983 * glib will terminate the program if it is unable to obtain memory
1984 * from the operating system). If an exception propagates from the
1985 * 'fail' callback, this will be consumed and a g_critical() warning
1986 * will be issued. The callback will execute in the glib main loop
1987 * whose GMainContext object is passed to the 'context' argument of
1988 * this method. An empty std::unique_ptr object indicates no 'fail'
1989 * callback.
1990 * @param fail_releaser A pointer to a Releaser object for automatic
1991 * disconnection of the 'fail' callback before it executes in a main
1992 * loop (mainly relevant if the callback represents a non-static
1993 * member function of an object which may be destroyed before the
1994 * callback executes). A value of 0/NULL/nullptr indicates no
1995 * releaser.
1996 * @param priority The priority to be given in the main loop to the
1997 * 'when' callback or any 'fail' callback. In ascending order of
1998 * priorities, priorities are G_PRIORITY_LOW,
1999 * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
2000 * and G_PRIORITY_HIGH. This determines the order in which the
2001 * callback will appear in the event list in the main loop, not the
2002 * priority which the OS will adopt.
2003 * @param context The glib main context of the main loop in which the
2004 * 'when' callback or any 'fail' callback is to be executed. A value
2005 * 0/NULL/nullptr will cause the callback to be executed in the main
2006 * program loop.
2007 * @param func The callable object to be executed as a task, such as
2008 * formed by a lambda expression or the result of std::bind. It
2009 * should return a value (it cannot return void). It must be fully
2010 * bound (that is, it must take no arguments when called). If an
2011 * exception propagates from the task, the exception will be consumed
2012 * and the 'fail' callback will execute.
2013 * @exception std::bad_alloc This exception will be thrown if memory
2014 * is exhausted and the system throws in that case. (On systems with
2015 * over-commit/lazy-commit combined with virtual memory (swap), it is
2016 * rarely useful to check for memory exhaustion). If this exception
2017 * is thrown, the task will not start (which also means that the
2018 * 'when' and 'fail' callbacks will not execute).
2019 * @exception Cgu::Thread::TaskError This exception will be thrown if
2020 * stop_all() has previously been called. It will also be thrown if
2021 * is_error() would return true because this class's internal thread
2022 * pool loop implementation has thrown std::bad_alloc, or a thread
2023 * has failed to start correctly. (On systems with
2024 * over-commit/lazy-commit combined with virtual memory (swap), it is
2025 * rarely useful to check for memory exhaustion, but there may be
2026 * some specialized cases where the return value of is_error() is
2027 * useful.) If this exception is thrown, the task will not start
2028 * (which also means that the 'when' and 'fail' callbacks will not
2029 * execute).
2030 * @note 1. This method will also throw if the copy or move
2031 * constructor of the callable object throws. If such an exception
2032 * is thrown, the task will not start (which also means that the
2033 * 'when' and 'fail' callbacks will not execute).
2034 * @note 2. If the callable object passed as an argument has both
2035 * const and non-const operator()() methods, the non-const version
2036 * will be called even if the callable object passed is a const
2037 * object.
2038 * @note 3. If a 'when_releaser' or a 'fail_releaser' argument is
2039 * provided, it is in theory possible (if memory is exhausted and the
2040 * system throws in that case) that an internal SafeEmitterArg object
2041 * will throw std::bad_alloc when emitting/executing the 'when' or
2042 * 'fail' callback in the glib main loop, with the result that the
2043 * relevant callback will not execute (instead the exception will be
2044 * consumed and a g_critical() warning will be issued). This is
2045 * rarely of any relevance because glib will abort the program if it
2046 * is itself unable to obtain memory from the operating system.
2047 * However, where it is relevant, design the program so that it is
2048 * not necessary to provide a releaser object.
2049 *
2050 * Since 2.0.14
2051 */
2052 template <class Ret, class Func>
2053 void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
2054 Cgu::Releaser* when_releaser,
2055 std::unique_ptr<const Cgu::Callback::Callback> fail,
2056 Cgu::Releaser* fail_releaser,
2057 gint priority,
2058 GMainContext* context,
2059 Func&& func);
2060
2061 /**
2062 * This is a wrapper which will take a callable object (such as a
2063 * std::function object, a lambda or the return value of std::bind)
2064 * representing a function which returns a value, and constructs a
2065 * TaskManager task which will execute that function by calling
2066 * add_task() with an appropriate callback object, and causes the
2067 * 'when' callback passed as an argument to this method to be
2068 * executed by a glib main loop if and when the task finishes
2069 * correctly - the 'when' callback is passed the function's return
2070 * value when it is invoked. It is thread safe (any thread may call
2071 * this method, including another task running on the TaskManager
2072 * object). Apart from the absence of a 'one thread per task' model,
2073 * this method therefore provides a similar interface to the one
2074 * provided by Cgu::Thread::Future. See the documentation on
2075 * add_task() for further information about how task execution works.
2076 *
2077 * Note that unlike add_task(), but like the 'fail' callback of
2078 * Cgu::Thread::Future objects, if a fail callback is provided to
2079 * this method and it executes, it will execute in the glib main loop
2080 * whose GMainContext object is passed to the 'context' argument of
2081 * this method.
2082 *
2083 * Note also that if releasers are provided for the 'when' or 'fail'
2084 * callbacks, these are passed by pointer and not by reference (this
2085 * is so that a NULL pointer can indicate that no releaser is to be
2086 * provided). If provided, a releaser will enable automatic
2087 * disconnection of the 'when' or 'fail' callback, if the object of
2088 * which the releaser is a member is destroyed. For this to be race
2089 * free, the lifetime of that object must be controlled by the thread
2090 * in whose main loop the 'when' or 'fail' callback will execute.
2091 *
2092 * The make_task_when() method is similar to this method but provides
2093 * an abbreviated set of parameters suitable for most cases. This
2094 * method is for use where releasers or a 'fail' callback are
2095 * required.
2096 *
2097 * @param when A callable object (such as formed by a lambda
2098 * expression or the result of std::bind) which will be executed if
2099 * and when the 'func' object passed to this method finishes
2100 * correctly. The 'when' callback is passed that objects's return
2101 * value when invoked, and should take a single unbound argument,
2102 * namely a reference to const of the type of that return value. If
2103 * an exception propagates from the 'when' callback, this will be
2104 * consumed and a g_critical() warning will be issued. The callback
2105 * will execute in the glib main loop whose GMainContext object is
2106 * passed to the 'context' argument of this method.
2107 * @param when_releaser A pointer to a Releaser object for automatic
2108 * disconnection of the 'when' callback before it executes in a main
2109 * loop (mainly relevant if the callback calls a non-static member
2110 * function of an object which may be destroyed before the callback
2111 * executes). A value of 0/NULL/nullptr indicates no releaser.
2112 * @param fail A callable object (such as formed by a lambda
2113 * expression or the result of std::bind) which will be executed if
2114 * the 'when' callback does not execute. This would happen if the
2115 * the callable object passed as 'func' to this method exits by
2116 * throwing Thread::Exit or some other exception, or if the 'when'
2117 * callback does not execute because the internal implementation of
2118 * this wrapper throws std::bad_alloc (which will not happen if the
2119 * library has been installed using the
2120 * –with-glib-memory-slices-no-compat configuration option: instead
2121 * glib will terminate the program if it is unable to obtain memory
2122 * from the operating system). The callable object must be fully
2123 * bound (that is, it must take no arguments when called). If an
2124 * exception propagates from the 'fail' callback, this will be
2125 * consumed and a g_critical() warning will be issued. The callback
2126 * will execute in the glib main loop whose GMainContext object is
2127 * passed to the 'context' argument of this method. If no 'fail'
2128 * callback is wanted, pass a lambda which does nothing.
2129 * @param fail_releaser A pointer to a Releaser object for automatic
2130 * disconnection of the 'fail' callback before it executes in a main
2131 * loop (mainly relevant if the callback calls a non-static member
2132 * function of an object which may be destroyed before the callback
2133 * executes). A value of 0/NULL/nullptr indicates no releaser.
2134 * @param priority The priority to be given in the main loop to the
2135 * 'when' callback or any 'fail' callback. In ascending order of
2136 * priorities, priorities are G_PRIORITY_LOW,
2137 * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
2138 * and G_PRIORITY_HIGH. This determines the order in which the
2139 * callback will appear in the event list in the main loop, not the
2140 * priority which the OS will adopt.
2141 * @param context The glib main context of the main loop in which the
2142 * 'when' callback or any 'fail' callback is to be executed. A value
2143 * 0/NULL/nullptr will cause the callback to be executed in the main
2144 * program loop.
2145 * @param func The callable object to be executed as a task, such as
2146 * formed by a lambda expression or the result of std::bind. It
2147 * should return a value (it cannot return void). It must be fully
2148 * bound (that is, it must take no arguments when called). If an
2149 * exception propagates from the task, the exception will be consumed
2150 * and the 'fail' callback will execute.
2151 * @exception std::bad_alloc This exception will be thrown if memory
2152 * is exhausted and the system throws in that case. (On systems with
2153 * over-commit/lazy-commit combined with virtual memory (swap), it is
2154 * rarely useful to check for memory exhaustion). If this exception
2155 * is thrown, the task will not start (which also means that the
2156 * 'when' and 'fail' callbacks will not execute).
2157 * @exception Cgu::Thread::TaskError This exception will be thrown if
2158 * stop_all() has previously been called. It will also be thrown if
2159 * is_error() would return true because this class's internal thread
2160 * pool loop implementation has thrown std::bad_alloc, or a thread
2161 * has failed to start correctly. (On systems with
2162 * over-commit/lazy-commit combined with virtual memory (swap), it is
2163 * rarely useful to check for memory exhaustion, but there may be
2164 * some specialized cases where the return value of is_error() is
2165 * useful.) If this exception is thrown, the task will not start
2166 * (which also means that the 'when' and 'fail' callbacks will not
2167 * execute).
2168 * @note 1. This method will also throw if the copy or move
2169 * constructor of the 'func', 'when' or 'fail' callable objects
2170 * throws. If such an exception is thrown, the task will not start
2171 * (which also means that the 'when' and 'fail' callbacks will not
2172 * execute).
2173 * @note 2. If any of the callable objects passed to this method have
2174 * both const and non-const operator()() methods, the non-const
2175 * version will be called even if the callable object passed is a
2176 * const object.
2177 * @note 3. If a 'when_releaser' or a 'fail_releaser' argument is
2178 * provided, it is in theory possible (if memory is exhausted and the
2179 * system throws in that case) that an internal SafeEmitterArg object
2180 * will throw std::bad_alloc when emitting/executing the 'when' or
2181 * 'fail' callback in the glib main loop, with the result that the
2182 * relevant callback will not execute (instead the exception will be
2183 * consumed and a g_critical() warning will be issued). This is
2184 * rarely of any relevance because glib will abort the program if it
2185 * is itself unable to obtain memory from the operating system.
2186 * However, where it is relevant, design the program so that it is
2187 * not necessary to provide a releaser object.
2188 *
2189 * Since 2.1.0
2190 */
2191 // we need to use enable_if so that where this function is passed
2192 // unique_ptr's holding non-const Callback::CallbackArg objects, or
2193 // some other convertible object, this templated overload is dropped
2194 // from the overload set, in order to support the unique_ptr
2195 // overloads of this function. This overload calls into the version
2196 // of this function taking CallbackArg objects by unique_ptr in
2197 // order to perform type erasure.
2198 template <class When, class Fail, class Func,
2199 class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value
2200 && !std::is_convertible<Fail, std::unique_ptr<const Callback::Callback>>::value>::type>
2201 void make_task_when_full(When&& when,
2202 Cgu::Releaser* when_releaser,
2203 Fail&& fail,
2204 Cgu::Releaser* fail_releaser,
2205 gint priority,
2206 GMainContext* context,
2207 Func&& func) {
2208 typedef decltype(func()) Ret;
2209 std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2210 Callback::lambda<const Ret&>(std::forward<When>(when))
2211 );
2212 std::unique_ptr<const Callback::Callback> fail_ptr(
2213 Callback::lambda<>(std::forward<Fail>(fail))
2214 );
2215 make_task_when_full(std::move(when_ptr),
2216 when_releaser,
2217 std::move(fail_ptr),
2218 fail_releaser,
2219 priority,
2220 context,
2221 std::forward<Func>(func));
2222 }
2223
2224 /**
2225 * This is an abbreviated version of make_task_when_full(), which is
2226 * for use when it is known that the callable object passed to this
2227 * method does not throw, and the user is not interested in
2228 * std::bad_alloc and does not need a Cgu::Releaser object for the
2229 * 'when' callback (which is likely to cover the majority of uses,
2230 * particularly when composing tasks using glib because glib
2231 * terminates the program if it is unable to obtain memory).
2232 *
2233 * Like make_task_when_full(), this method is a wrapper which will
2234 * take a callable object which returns a value, and constructs a
2235 * TaskManager task which will execute that object by calling
2236 * add_task() with an appropriate callback object, and causes the
2237 * 'when' callback passed as an argument to this method to be
2238 * executed by a glib main loop if and when the task finishes
2239 * correctly - the 'when' callback is passed the callable object's
2240 * return value when it is invoked. It is thread safe (any thread
2241 * may call this method, including another task running on the
2242 * TaskManager object). Apart from the absence of a 'one thread per
2243 * task' model, this method therefore provides a similar interface to
2244 * the one provided by Cgu::Thread::Future. See the documentation on
2245 * add_task() for further information about how task execution works.
2246 *
2247 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2248 * in the main loop.
2249 *
2250 * There is a similar make_task_compose() function which has the
2251 * callable object to be executed as a task as its first argument and
2252 * the 'when' callback as its last argument, in order to aid task
2253 * composition.
2254 *
2255 * @param when A callback which will be executed if and when the
2256 * callable object passed to this method finishes correctly. The
2257 * callback is passed that object's return value when it is invoked.
2258 * If an exception propagates from the 'when' callback, this will be
2259 * consumed and a g_critical() warning will be issued. The callback
2260 * will execute in the glib main loop whose GMainContext object is
2261 * passed to the 'context' argument of this method.
2262 * @param context The glib main context of the main loop in which the
2263 * 'when' callback is to be executed. A value 0/NULL/nullptr will
2264 * cause the callback to be executed in the main program loop.
2265 * @param f The callable object to be executed as a task, such as
2266 * formed by a lambda expression or the result of std::bind. It
2267 * should return a value (it cannot return void). It must be fully
2268 * bound (that is, it must take no arguments when called). If an
2269 * exception propagates from the task, the exception will be consumed
2270 * and (if the thrown object's type is not Cgu::Thread::Exit) a
2271 * g_critical() warning will be issued.
2272 * @exception std::bad_alloc This exception will be thrown if memory
2273 * is exhausted and the system throws in that case. (On systems with
2274 * over-commit/lazy-commit combined with virtual memory (swap), it is
2275 * rarely useful to check for memory exhaustion). If this exception
2276 * is thrown, the task will not start (which also means that the
2277 * 'when' callback will not execute).
2278 * @exception Cgu::Thread::TaskError This exception will be thrown if
2279 * stop_all() has previously been called. It will also be thrown if
2280 * is_error() would return true because this class's internal thread
2281 * pool loop implementation has thrown std::bad_alloc, or a thread
2282 * has failed to start correctly. (On systems with
2283 * over-commit/lazy-commit combined with virtual memory (swap), it is
2284 * rarely useful to check for memory exhaustion, but there may be
2285 * some specialized cases where the return value of is_error() is
2286 * useful.) If this exception is thrown, the task will not start
2287 * (which also means that the 'when' callback will not execute).
2288 * @note 1. This method will also throw if the copy or move
2289 * constructor of the callable object throws. If such an exception
2290 * is thrown, the task will not start (which also means that the
2291 * 'when' callback will not execute).
2292 * @note 2. If the callable object passed as an argument has both
2293 * const and non-const operator()() methods, the non-const version
2294 * will be called even if the callable object passed is a const
2295 * object.
2296 *
2297 * Since 2.0.14
2298 */
2299 template <class Ret, class Func>
2300 void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
2301 GMainContext* context,
2302 Func&& f) {
2303 make_task_when_full(std::move(when),
2304 0,
2305 std::unique_ptr<const Cgu::Callback::Callback>(),
2306 0,
2307 G_PRIORITY_DEFAULT,
2308 context,
2309 std::forward<Func>(f));
2310 }
2311
2312 /**
2313 * This is an abbreviated version of make_task_when_full(), which is
2314 * for use when it is known that the callable object passed to the
2315 * 'func' argument of this method does not throw, and the user is not
2316 * interested in std::bad_alloc and does not need a Cgu::Releaser
2317 * object for the 'when' callback (which is likely to cover the
2318 * majority of uses, particularly when composing tasks using glib
2319 * because glib terminates the program if it is unable to obtain
2320 * memory).
2321 *
2322 * Like make_task_when_full(), this method is a wrapper which takes a
2323 * callable object which returns a value as its 'func' argument, and
2324 * constructs a TaskManager task which will execute that object by
2325 * calling add_task() with an appropriate callback object, and causes
2326 * the 'when' callback passed as an argument to this method to be
2327 * executed by a glib main loop if and when the task finishes
2328 * correctly - the 'when' callback is passed the return value of the
2329 * 'func' argument when it is invoked. It is thread safe (any thread
2330 * may call this method, including another task running on the
2331 * TaskManager object). Apart from the absence of a 'one thread per
2332 * task' model, this method therefore provides a similar interface to
2333 * the one provided by Cgu::Thread::Future. See the documentation on
2334 * add_task() for further information about how task execution works.
2335 *
2336 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2337 * in the main loop.
2338 *
2339 * There is a similar make_task_compose() function which has the
2340 * callable object to be executed as a task as its first argument and
2341 * the 'when' callback as its last argument, in order to aid task
2342 * composition.
2343 *
2344 * @param when A callable object (such as formed by a lambda
2345 * expression or the result of std::bind) which will be executed if
2346 * and when the 'func' object passed to this method finishes
2347 * correctly. The 'when' callback is passed that objects's return
2348 * value when invoked, and should take a single unbound argument,
2349 * namely a reference to const of the type of that return value. If
2350 * an exception propagates from the 'when' callback, this will be
2351 * consumed and a g_critical() warning will be issued. The callback
2352 * will execute in the glib main loop whose GMainContext object is
2353 * passed to the 'context' argument of this method.
2354 * @param context The glib main context of the main loop in which the
2355 * 'when' callback is to be executed. A value 0/NULL/nullptr will
2356 * cause the callback to be executed in the main program loop.
2357 * @param func The callable object to be executed as a task, such as
2358 * formed by a lambda expression or the result of std::bind. It
2359 * should return a value (it cannot return void). It must be fully
2360 * bound (that is, it must take no arguments when called). If an
2361 * exception propagates from the task, the exception will be consumed
2362 * and (if the thrown object's type is not Cgu::Thread::Exit) a
2363 * g_critical() warning will be issued.
2364 * @exception std::bad_alloc This exception will be thrown if memory
2365 * is exhausted and the system throws in that case. (On systems with
2366 * over-commit/lazy-commit combined with virtual memory (swap), it is
2367 * rarely useful to check for memory exhaustion). If this exception
2368 * is thrown, the task will not start (which also means that the
2369 * 'when' callback will not execute).
2370 * @exception Cgu::Thread::TaskError This exception will be thrown if
2371 * stop_all() has previously been called. It will also be thrown if
2372 * is_error() would return true because this class's internal thread
2373 * pool loop implementation has thrown std::bad_alloc, or a thread
2374 * has failed to start correctly. (On systems with
2375 * over-commit/lazy-commit combined with virtual memory (swap), it is
2376 * rarely useful to check for memory exhaustion, but there may be
2377 * some specialized cases where the return value of is_error() is
2378 * useful.) If this exception is thrown, the task will not start
2379 * (which also means that the 'when' callback will not execute).
2380 * @note 1. This method will also throw if the copy or move
2381 * constructor of the 'func' or 'when' callable objects throws. If
2382 * such an exception is thrown, the task will not start (which also
2383 * means that the 'when' callback will not execute).
2384 * @note 2. If any of the callable objects passed to this method have
2385 * both const and non-const operator()() methods, the non-const
2386 * version will be called even if the callable object passed is a
2387 * const object.
2388 *
2389 * Since 2.1.0
2390 */
2391 // we need to use enable_if so that where this function is passed a
2392 // unique_ptr holding a non-const Callback::CallbackArg object, or
2393 // some other convertible object, this templated overload is dropped
2394 // from the overload set, in order to support the unique_ptr
2395 // overloads of this function. This overload calls into the version
2396 // of this function taking a CallbackArg object by unique_ptr in
2397 // order to perform type erasure.
2398 template <class When, class Func,
2399 class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value>::type>
2400 void make_task_when(When&& when,
2401 GMainContext* context,
2402 Func&& func) {
2403 typedef decltype(func()) Ret;
2404 std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2405 Callback::lambda<const Ret&>(std::forward<When>(when))
2406 );
2407 make_task_when_full(std::move(when_ptr),
2408 0,
2409 std::unique_ptr<const Cgu::Callback::Callback>(),
2410 0,
2411 G_PRIORITY_DEFAULT,
2412 context,
2413 std::forward<Func>(func));
2414 }
2415
2416 /**
2417 * This is an abbreviated version of make_task_when_full(), which is
2418 * for use when it is known that the callable object passed to this
2419 * method does not throw, and the user is not interested in
2420 * std::bad_alloc and does not need a Cgu::Releaser object for the
2421 * 'when' callback (which is likely to cover the majority of uses,
2422 * particularly when composing tasks using glib because glib
2423 * terminates the program if it is unable to obtain memory).
2424 *
2425 * This method does the same as the version of make_task_when()
2426 * taking a callable object, except that this method takes that
2427 * object as its first argument and the 'when' callback as its last
2428 * argument in order to aid task composition, and in particular so
2429 * tasks compose in user code in a visually ordered manner.
2430 *
2431 * More particularly, like make_task_when_full(), this method is a
2432 * wrapper which will take a callable object which returns a value,
2433 * and constructs a TaskManager task which will execute that object
2434 * by calling add_task() with an appropriate callback object, and
2435 * causes the 'when' callback passed as an argument to this method to
2436 * be executed by a glib main loop if and when the task finishes
2437 * correctly - the 'when' callback is passed the callable object's
2438 * return value when it is invoked. It is thread safe (any thread
2439 * may call this method, including another task running on the
2440 * TaskManager object). Apart from the absence of a 'one thread per
2441 * task' model, this method therefore provides a similar interface to
2442 * the one provided by Cgu::Thread::Future. See the documentation on
2443 * add_task() for further information about how task execution works.
2444 *
2445 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2446 * in the main loop.
2447 *
2448 * @param f The callable object to be executed as a task, such as
2449 * formed by a lambda expression or the result of std::bind. It
2450 * should return a value (it cannot return void). It must be fully
2451 * bound (that is, it must take no arguments when called). If an
2452 * exception propagates from the task, the exception will be consumed
2453 * and (if the thrown object's type is not Cgu::Thread::Exit) a
2454 * g_critical() warning will be issued.
2455 * @param context The glib main context of the main loop in which the
2456 * 'when' callback is to be executed. A value 0/NULL/nullptr will
2457 * cause the callback to be executed in the main program loop.
2458 * @param when A callback which will be executed if and when the
2459 * callable object passed to this method finishes correctly. The
2460 * callback is passed that object's return value when it is invoked.
2461 * If an exception propagates from the 'when' callback, this will be
2462 * consumed and a g_critical() warning will be issued. The callback
2463 * will execute in the glib main loop whose GMainContext object is
2464 * passed to the 'context' argument of this method.
2465 * @exception std::bad_alloc This exception will be thrown if memory
2466 * is exhausted and the system throws in that case. (On systems with
2467 * over-commit/lazy-commit combined with virtual memory (swap), it is
2468 * rarely useful to check for memory exhaustion). If this exception
2469 * is thrown, the task will not start (which also means that the
2470 * 'when' callback will not execute).
2471 * @exception Cgu::Thread::TaskError This exception will be thrown if
2472 * stop_all() has previously been called. It will also be thrown if
2473 * is_error() would return true because this class's internal thread
2474 * pool loop implementation has thrown std::bad_alloc, or a thread
2475 * has failed to start correctly. (On systems with
2476 * over-commit/lazy-commit combined with virtual memory (swap), it is
2477 * rarely useful to check for memory exhaustion, but there may be
2478 * some specialized cases where the return value of is_error() is
2479 * useful.) If this exception is thrown, the task will not start
2480 * (which also means that the 'when' callback will not execute).
2481 * @note 1. This method will also throw if the copy or move
2482 * constructor of the callable object throws. If such an exception
2483 * is thrown, the task will not start (which also means that the
2484 * 'when' callback will not execute).
2485 * @note 2. If the callable object passed as an argument has both
2486 * const and non-const operator()() methods, the non-const version
2487 * will be called even if the callable object passed is a const
2488 * object.
2489 *
2490 * Since 2.0.14
2491 */
2492 template <class Ret, class Func>
2493 void make_task_compose(Func&& f,
2494 GMainContext* context,
2495 std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when) {
2496 make_task_when_full(std::move(when),
2497 0,
2498 std::unique_ptr<const Cgu::Callback::Callback>(),
2499 0,
2500 G_PRIORITY_DEFAULT,
2501 context,
2502 std::forward<Func>(f));
2503 }
2504
2505 /**
2506 * This is an abbreviated version of make_task_when_full(), which is
2507 * for use when it is known that the callable object passed to the
2508 * 'func' argument of this method does not throw, and the user is not
2509 * interested in std::bad_alloc and does not need a Cgu::Releaser
2510 * object for the 'when' callback (which is likely to cover the
2511 * majority of uses, particularly when composing tasks using glib
2512 * because glib terminates the program if it is unable to obtain
2513 * memory).
2514 *
2515 * This method does the same as make_task_when(), except that this
2516 * method takes the callable object to be executed as a task as its
2517 * first argument and the 'when' callback as its last argument in
2518 * order to aid task composition, and in particular so tasks compose
2519 * in user code in a visually ordered manner.
2520 *
2521 * More particularly, like make_task_when_full(), this method is a
2522 * wrapper which takes a callable object which returns a value as its
2523 * 'func' argument, and constructs a TaskManager task which will
2524 * execute that object by calling add_task() with an appropriate
2525 * callback object, and causes the 'when' callback passed as an
2526 * argument to this method to be executed by a glib main loop if and
2527 * when the task finishes correctly - the 'when' callback is passed
2528 * the return value of the 'func' argument when it is invoked. It is
2529 * thread safe (any thread may call this method, including another
2530 * task running on the TaskManager object). Apart from the absence
2531 * of a 'one thread per task' model, this method therefore provides a
2532 * similar interface to the one provided by Cgu::Thread::Future. See
2533 * the documentation on add_task() for further information about how
2534 * task execution works.
2535 *
2536 * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2537 * in the main loop.
2538 *
2539 * @param func The callable object to be executed as a task, such as
2540 * formed by a lambda expression or the result of std::bind. It
2541 * should return a value (it cannot return void). It must be fully
2542 * bound (that is, it must take no arguments when called). If an
2543 * exception propagates from the task, the exception will be consumed
2544 * and (if the thrown object's type is not Cgu::Thread::Exit) a
2545 * g_critical() warning will be issued.
2546 * @param context The glib main context of the main loop in which the
2547 * 'when' callback is to be executed. A value 0/NULL/nullptr will
2548 * cause the callback to be executed in the main program loop.
2549 * @param when A callable object (such as formed by a lambda
2550 * expression or the result of std::bind) which will be executed if
2551 * and when the 'func' object passed to this method finishes
2552 * correctly. The 'when' callback is passed that objects's return
2553 * value when invoked, and should take a single unbound argument,
2554 * namely a reference to const of the type of that return value. If
2555 * an exception propagates from the 'when' callback, this will be
2556 * consumed and a g_critical() warning will be issued. The callback
2557 * will execute in the glib main loop whose GMainContext object is
2558 * passed to the 'context' argument of this method.
2559 * @exception std::bad_alloc This exception will be thrown if memory
2560 * is exhausted and the system throws in that case. (On systems with
2561 * over-commit/lazy-commit combined with virtual memory (swap), it is
2562 * rarely useful to check for memory exhaustion). If this exception
2563 * is thrown, the task will not start (which also means that the
2564 * 'when' callback will not execute).
2565 * @exception Cgu::Thread::TaskError This exception will be thrown if
2566 * stop_all() has previously been called. It will also be thrown if
2567 * is_error() would return true because this class's internal thread
2568 * pool loop implementation has thrown std::bad_alloc, or a thread
2569 * has failed to start correctly. (On systems with
2570 * over-commit/lazy-commit combined with virtual memory (swap), it is
2571 * rarely useful to check for memory exhaustion, but there may be
2572 * some specialized cases where the return value of is_error() is
2573 * useful.) If this exception is thrown, the task will not start
2574 * (which also means that the 'when' callback will not execute).
2575 * @note 1. This method will also throw if the copy or move
2576 * constructor of the 'func' or 'when' callable objects throws. If
2577 * such an exception is thrown, the task will not start (which also
2578 * means that the 'when' callback will not execute).
2579 * @note 2. If any of the callable objects passed to this method have
2580 * both const and non-const operator()() methods, the non-const
2581 * version will be called even if the callable object passed is a
2582 * const object.
2583 *
2584 * Since 2.1.0
2585 */
2586 // we need to use enable_if so that where this function is passed a
2587 // unique_ptr holding a non-const Callback::CallbackArg object, or
2588 // some other convertible object, this templated overload is dropped
2589 // from the overload set, in order to support the unique_ptr
2590 // overloads of this function. This overload calls into the version
2591 // of this function taking a CallbackArg object by unique_ptr in
2592 // order to perform type erasure.
2593 template <class Func, class When,
2594 class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value>::type>
2595 void make_task_compose(Func&& func,
2596 GMainContext* context,
2597 When&& when) {
2598 typedef decltype(func()) Ret;
2599 std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2600 Callback::lambda<const Ret&>(std::forward<When>(when))
2601 );
2602 make_task_when_full(std::move(when_ptr),
2603 0,
2604 std::unique_ptr<const Cgu::Callback::Callback>(),
2605 0,
2606 G_PRIORITY_DEFAULT,
2607 context,
2608 std::forward<Func>(func));
2609 }
2610
2611 /**
2612 * If the specified minimum number of threads is greater than 0, this
2613 * constructor will start the required minimum number of threads. If
2614 * glib < 2.32 is installed, g_thread_init() must be called before
2615 * any TaskManager objects are constructed
2616 * @param max The maximum number of threads which the TaskManager
2617 * object will run in the thread pool. If the value passed as this
2618 * argument is less than the value passed as 'min', the maximum
2619 * number of threads will be set to 'min'. A value of 0 is not
2620 * valid, and if this is passed the number will be set to the greater
2621 * of 1 and 'min'.
2622 * @param min The minimum number of threads which the TaskManager
2623 * object will run in the thread pool.
2624 * @param idle The length of time in milliseconds that threads
2625 * greater in number than 'min' and not executing any tasks will
2626 * remain in existence. The default is 10000 (10 seconds).
2627 * @param blocking If true, calls to stop_all() and the destructor
2628 * will not return until the tasks remaining to be executed have
2629 * finished (what is meant by "the tasks remaining to be executed"
2630 * depends on the StopMode setting, for which see the documentation
2631 * on the stop_all() method). If false, stop_all() and the
2632 * destructor will return straight away (which in terms of the
2633 * TaskManager class implementation is safe for the reasons explained
2634 * in the documentation on the destructor).
2635 * @param mode The StopMode setting (either
2636 * Cgu::Thread::TaskManager::wait_for_running or
2637 * Cgu::Thread::TaskManager::wait_for_all) executed when running
2638 * stop_all() or when the destructor is called. See the
2639 * documentation on stop_all() for an explanation of the setting.
2640 * @exception std::bad_alloc This exception might be thrown if memory
2641 * is exhausted and the system throws in that case.
2642 * @exception Cgu::Thread::TaskError This exception will be thrown if
2643 * starting the specified minimum number of threads fails.
2644 * @exception Cgu::Thread::MutexError This exception might be thrown
2645 * if initialisation of the contained mutex fails. (It is often not
2646 * worth checking for this, as it means either memory is exhausted or
2647 * pthread has run out of other resources to create new mutexes.)
2648 * @exception Cgu::Thread::CondError This exception might be thrown
2649 * if initialisation of the contained condition variable fails. (It
2650 * is often not worth checking for this, as it means either memory is
2651 * exhausted or pthread has run out of other resources to create new
2652 * condition variables.)
2653 *
2654 * Since 2.0.12
2655 */
2656 TaskManager(unsigned int max = 8, unsigned int min = 0,
2657 unsigned int idle = 10000, bool blocking = true,
2658 StopMode mode = TaskManager::wait_for_all);
2659
2660 /**
2661 * The destructor will call stop_all(), unless that method has
2662 * previously been called explicitly without throwing std::bad_alloc.
2663 * If the blocking setting is true, the destructor will not return
2664 * until the tasks remaining to be executed have finished (what is
2665 * meant by "the tasks remaining to be executed" depends on the
2666 * StopMode setting, for which see the documentation on the
2667 * stop_all() method.) If the blocking setting is false, the
2668 * destructor will return straight away: this is safe, because
2669 * TaskManager's internals for running tasks have been implemented
2670 * using reference counting and will not be deleted until all threads
2671 * running on the TaskManager object have finished, although the
2672 * remaining tasks should not attempt to call any of TaskManager's
2673 * methods once the TaskManager object itself has been destroyed.
2674 *
2675 * The destructor is thread safe (any thread can destroy a
2676 * TaskManager object) unless the blocking setting is true, in which
2677 * case no task running on the TaskManager object may destroy the
2678 * TaskManager object. Subject to that, it is not an error for a
2679 * thread to destroy a TaskManager object and so invoke this
2680 * destructor while another thread is already blocking in (if the
2681 * blocking setting is true) or already out of (if the blocking
2682 * setting is false) a call to stop_all() and remaining tasks are
2683 * executing: if blocking, both calls (to stop_all() and to this
2684 * destructor) would safely block together. Any given thread can
2685 * similarly safely follow a non-blocking call to stop_all() by a
2686 * non-blocking call to this destructor even though remaining tasks
2687 * are executing. However, it is an error for a thread to call
2688 * stop_all() after another thread has begun destruction of the
2689 * TaskManager object (that is, after this destructor has been
2690 * entered): there would then be an unresolvable race with the
2691 * destructor.
2692 *
2693 * The destructor will not throw.
2694 *
2695 * If stop_all() has not previously been called explicitly and throws
2696 * std::bad_alloc() when called in this destructor, the exception
2697 * will be caught and consumed, but then the destructor will not
2698 * block even if the blocking setting is true, and if the minimum
2699 * number of threads is not 0 some threads might remain running
2700 * during the entire program duration (albeit safely). Where the
2701 * throwing of std::bad_alloc is a meaningful event (usually it
2702 * isn't) and needs to be guarded against, call stop_all() explicitly
2703 * before this destructor is entered, or use a minimum thread value
2704 * of 0 and allow for the case of the destructor not blocking.
2705 *
2706 * Since 2.0.12
2707 */
2708 ~TaskManager();
2709
2710 /* Only has effect if --with-glib-memory-slices-compat or
2711 * --with-glib-memory-slices-no-compat option picked */
2712 CGU_GLIB_MEMORY_SLICES_FUNCS
2713 };
2714
2715 /**
2716 * @class TaskManager::IncHandle task_manager.h c++-gtk-utils/task_manager.h
2717 * @brief A scoped handle for exception safe incrementing of the
2718 * maximum number of threads that a TaskManager object will run.
2719 * @sa Thread::TaskManager
2720 *
2721 * This class is for use where a task running on a TaskManager object
2722 * is about to make a blocking call. It enables the task to
2723 * increment in an exception safe way the maximum number of tasks
2724 * which the TaskManager object will currently run in its thread pool
2725 * to enable another thread to keep a core active, so that the number
2726 * is automatically decremented again when the
2727 * ThreadManager::IncHandle object has gone out of scope after the
2728 * task has finished making blocking calls or something has thrown.
2729 *
2730 * The documentation on Thread::TaskManager gives an example of its
2731 * use.
2732 *
2733 * This class is available since version 2.2.1 of the library.
2734 */
2735 class TaskManager::IncHandle {
2736 TaskManager& tm;
2737 public:
2738 /**
2739 * This class cannot be copied. The copy constructor is deleted.
2740 *
2741 * Since 2.0.18/2.2.1
2742 */
2743 IncHandle(const TaskManager::IncHandle&) = delete;
2744
2745 /**
2746 * This class cannot be copied. The assignment operator is deleted.
2747 *
2748 * Since 2.0.18/2.2.1
2749 */
2750 TaskManager::IncHandle& operator=(const TaskManager::IncHandle&) = delete;
2751
2752 /**
2753 * This class requires initialisation with a TaskManager object. The
2754 * default constructor is deleted.
2755 *
2756 * Since 2.0.18/2.2.1
2757 */
2758 IncHandle() = delete;
2759
2760 /**
2761 * This constructor calls TaskManager::change_max_threads() to
2762 * increment the maximum number of threads a TaskManager object will
2763 * currently run in its thread pool.
2764 * @param tm_ The TaskManager object whose maximum thread limit is to
2765 * be incremented.
2766 * @exception std::bad_alloc If tasks are currently queued for
2767 * execution, a new thread will be started, so this exception may be
2768 * thrown on starting the thread if memory is exhausted and the
2769 * system throws in that case. (On systems with
2770 * over-commit/lazy-commit combined with virtual memory (swap), it is
2771 * rarely useful to check for memory exhaustion).
2772 * @exception Cgu::Thread::TaskError If tasks are currently queued
2773 * for execution, a new thread will be started, so this exception may
2774 * be thrown on starting the thread if it fails to start correctly
2775 * (this would mean that memory is exhausted, the pthread thread
2776 * limit has been reached or pthread has run out of other resources
2777 * to start new threads).
2778 *
2779 * Since 2.0.18/2.2.1
2780 */
2781 explicit IncHandle(TaskManager& tm_): tm(tm_) {
2782 tm_.change_max_threads(1);
2783 }
2784
2785 /**
2786 * This destructor calls TaskManager::change_max_threads() to
2787 * decrement the maximum number of threads a TaskManager object will
2788 * currently run in its thread pool. It will not throw.
2789 *
2790 * Since 2.0.18/2.2.1
2791 */
2792 ~IncHandle() {tm.change_max_threads(-1);}
2793 };
2794
2795 } // namespace Thread
2796
2797 } // namespace Cgu
2798
2799 #include <c++-gtk-utils/task_manager.tpp>
2800
2801 #endif