c++-gtk-utils
task_manager.h
Go to the documentation of this file.
1 /* Copyright (C) 2012 to 2016 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 <future> // for std::future and std::packaged_task
47 #include <type_traits> // for std::remove_reference, std::remove_const, std::enable_if,
48  // std::is_convertible and std::result_of
49 
50 #include <c++-gtk-utils/callback.h>
51 #include <c++-gtk-utils/thread.h>
52 #include <c++-gtk-utils/mutex.h>
56 #include <c++-gtk-utils/emitter.h>
58 
59 namespace Cgu {
60 
61 namespace Thread {
62 
63 struct TaskError: public std::exception {
64  virtual const char* what() const throw() {return "TaskError\n";}
65 };
66 
67 /**
68  * @class Cgu::Thread::TaskManager task_manager.h c++-gtk-utils/task_manager.h
69  * @brief A thread-pool class for managing tasks in multi-threaded programs.
70  * @sa Cgu::Thread::Future Cgu::AsyncResult Cgu::AsyncQueueDispatch Cgu::AsyncChannel Cgu::Callback::post() Cgu::Thread::TaskManager::IncHandle Cgu::Thread::parallel_for_each() Cgu::Thread::parallel_for_each_partial() Cgu::Thread::parallel_transform() Cgu::Thread::parallel_transform_partial()
71  *
72  * Cgu::Thread::Future operates on the principle of there being one
73  * worker thread per task. In some cases however, it may be better to
74  * have a limited pool of worker threads executing a larger number of
75  * tasks. This class implements this approach via a thread pool.
76  *
77  * One common approach for thread pools of this kind is to set the
78  * maximum number of threads to the number of cores, or some number
79  * less than the number of cores, available on the local machine. How
80  * that can be determined is system specific (on linux it can be
81  * obtained by, for example, counting the 'processor' fields in
82  * /proc/cpuinfo or by using sysconf with the glibc extension for
83  * _SC_NPROCESSORS_ONLN). From version 2.36, glib has a
84  * g_get_num_processors() function. From gcc-4.7, C++11's
85  * std::thread::hardware_concurrency() static member function is also
86  * available.
87  *
88  * The most general way of creating a new task is to call
89  * TaskManager::add_task() with a callable object (such as a lambda
90  * expression or the return value of std::bind) which returns void,
91  * although add_task() will also take a Callback::Callback object.
92  * Where the task needs to provide a result, two approaches can be
93  * adopted. First, the task callback can have a Cgu::AsyncResult
94  * object held by Cgu::SharedLockPtr (or by std::shared_ptr having a
95  * thread safe reference count) bound to it, or it can execute a
96  * std::packaged_task object from which it can obtain a std::future
97  * object. Alternatively, a task can provide a result asynchronously
98  * to a glib main loop by calling Cgu::Callback::post() when it is
99  * ready to do so. The TaskManager::make_task_result(),
100  * TaskManager::make_task_packaged(), TaskManager::make_task_when(),
101  * TaskManager::make_task_when_full(),
102  * TaskManager::make_task_compose(),
103  * TaskManager::make_task_packaged_when() and
104  * TaskManager::make_task_packaged_compose() convenience wrapper
105  * methods are provided which will set this up for you (including
106  * constructing appropriate task callbacks). This would normally be
107  * done by passing one of those functions a callable object which
108  * returns a value, such as a lambda expression or the return value of
109  * std::bind. Tasks can add other tasks, enabling the composition of
110  * an arbitrary number of tasks to obtain a final result.
111  *
112  * Overloads of TaskManager::make_task_result(),
113  * TaskManager::make_task_when() and
114  * TaskManager::make_task_when_full() also exist which take a function
115  * pointer (or an object reference and member function pointer) to a
116  * function which returns a value, with bound arguments, but these are
117  * deprecated in the 2.2 series of the library as they offer little
118  * advantage over using std::bind. (Although deprecated, there is no
119  * plan to remove these functions as they are there and they work -
120  * the deprecation is in effect guidance.) These deprecated functions
121  * can take up to three bound arguments in the case of a non-static
122  * member function, and four bound arguments in the case of any other
123  * function. In the case of a non-static member function, the
124  * referenced object whose member function is to be called must remain
125  * in existence until the task has completed. The target function
126  * passed by pointer (or member function pointer) can take a reference
127  * to const argument, as a copy of the object to be passed to the
128  * argument is taken to avoid dangling references, but it cannot take
129  * a reference to non-const argument.
130  *
131  * Copying of the return value of the target function or callable
132  * object represented by the task may take place. When a task
133  * completes, the return value will be stored, either in a
134  * Cgu::AsyncResult object (if TaskManager::make_task_result() is
135  * called) or in the shared state of a std::packaged_task object (if
136  * TaskManager::make_task_packaged(),
137  * TaskManager::make_task_packaged_when() or
138  * TaskManager::make_task_packaged_compose() is called) or for the
139  * purposes of executing the 'when' callback in a glib main loop (if
140  * TaskManager::make_task_when(), TaskManager::make_task_when_full()
141  * or TaskManager::make_task_compose() are called). This storage will
142  * therefore cause the return value type's assignment operator or copy
143  * constructor to be called once unless that type has a move
144  * assignment operator or move constructor, in which case a move
145  * operation will be made where possible. Note that a 'when' callback
146  * takes the stored return value by reference and so without any
147  * additional copying upon the 'when' callback being executed in the
148  * main loop.
149  *
150  * TaskManager objects do not provide thread cancellation. Thread
151  * cancellation is incompatible with the task-centred thread pool
152  * model. If task cancellation is wanted, use a Cgu::Thread::Future
153  * (or Cgu::Thread::Thread or Cgu::Thread::JoinableHandle) object
154  * instead, and have a dedicated thread for the cancelable task.
155  *
156  * If glib < 2.32 is installed, g_thread_init() must be called before
157  * any TaskManager objects are constructed, which in turn means that
158  * with glib < 2.32 TaskManager objects may not be constructed as
159  * static objects in global namespace (that is, before g_thread_init()
160  * has been called in the program).
161  *
162  * Any exceptions which propagate from a task will be consumed to
163  * protect the TaskManager object, and to detect whether this has
164  * happened there is a version of the TaskManager::add_task() method
165  * which takes a second argument comprising a 'fail' callback. If an
166  * exception propagates from the 'fail' callback that is also consumed
167  * and a g_critical() message issued.
168  * TaskManager::make_task_when_full() also provides for a 'fail'
169  * callback. TaskManager::make_task_packaged(),
170  * TaskManager::make_task_packaged_when() and
171  * TaskManager::make_task_packaged_compose() instead store an
172  * exception thrown by a task in the shared state of a
173  * std::packaged_task object, so that it is assessible from the
174  * associated std::future object.
175  *
176  * Tasks can be aborted by throwing Cgu::Thread::Exit (as well as any
177  * other exception). Where a task is managed by a TaskManager object,
178  * throwing Cgu::Thread::Exit will only terminate the task and not the
179  * thread on which it is running (and will cause the 'fail' callback
180  * to be executed, if there is one).
181  *
182  * Any 'fail' callback passed to TaskManager::add_task() or
183  * TaskManager::make_task_when_full() must be fully bound. Whilst a
184  * task can pass error status to the 'fail' callback via shared data
185  * bound to both the task and the 'fail' callback (held by, say, a
186  * SharedLockPtr object), or a global error stack, 'fail' callbacks
187  * are generally best reserved for use with entirely unexpected
188  * exceptions, where the most reasonable course is to perform some
189  * orderly logging and shutdown. For handlable exceptions, in an
190  * asynchronous environment the best course is often to catch them and
191  * deal with them in the task itself and (where
192  * TaskManager::make_task_when_full(), TaskManager::make_task_when()
193  * or TaskManager::make_task_compose() is employed) return a value of
194  * the task function's return type indicating no result.
195  * Alternatively, as mentioned above,
196  * TaskManager::make_task_packaged(),
197  * TaskManager::make_task_packaged_when() and
198  * TaskManager::make_task_packaged_compose() store an exception thrown
199  * by a task in the shared state of a std::packaged_task object
200  *
201  * TaskManager objects have no copy constructor or copy assignment
202  * operator, as copying them would have no obvious semantic meaning.
203  * Whilst swapping or moving TaskManager objects would be meaningful,
204  * this is not implemented either because it would require an
205  * additional internal lock to be thread safe, and the circumstances
206  * in which moving or swapping would be useful are limited. Where a
207  * move option is wanted, a TaskManager object can be constructed on
208  * free store and held by std::unique_ptr.
209  *
210  * Here is a compilable example of the calculator class referred to in
211  * the documentation on the AsyncResult but which uses a TaskManager
212  * object so that the calculator class can run more than one thread to
213  * service its calculations, using TaskManager::make_task_result():
214  *
215  * @code
216  * #include <vector>
217  * #include <numeric>
218  * #include <ostream>
219  * #include <iostream>
220  *
221  * #include <glib.h>
222  *
223  * #include <c++-gtk-utils/task_manager.h>
224  * #include <c++-gtk-utils/async_result.h>
225  * #include <c++-gtk-utils/shared_ptr.h>
226  *
227  * using namespace Cgu;
228  *
229  * class Calcs {
230  * Thread::TaskManager tm;
231  * public:
232  * SharedLockPtr<AsyncResult<double>> mean(const std::vector<double>& nums) {
233  * return tm.make_task_result([=]() -> double {
234  * if (nums.empty()) return 0.0;
235  * return std::accumulate(nums.begin(), nums.end(), 0.0)/nums.size();
236  * });
237  * }
238  *
239  * // ... other calculation methods here
240  * };
241  *
242  * int main () {
243  *
244  * g_thread_init(0);
245  * Calcs calcs;
246  * auto res1 = calcs.mean({1, 2, 8, 0});
247  * auto res2 = calcs.mean({101, 53.7, 87, 1.2});
248  *
249  * // ... do something else
250  * std::cout << res1->get() << std::endl;
251  * std::cout << res2->get() << std::endl;
252  *
253  * }
254  * @endcode
255  *
256  * The same could be done using TaskManager::make_task_packaged() as follows:
257  *
258  * @code
259  * #include <vector>
260  * #include <numeric>
261  * #include <ostream>
262  * #include <iostream>
263  * #include <future>
264  *
265  * #include <glib.h>
266  *
267  * #include <c++-gtk-utils/task_manager.h>
268  * #include <c++-gtk-utils/async_result.h>
269  * #include <c++-gtk-utils/shared_ptr.h>
270  *
271  * using namespace Cgu;
272  *
273  * class Calcs {
274  * Thread::TaskManager tm;
275  * public:
276  * std::future<double> mean(const std::vector<double>& nums) {
277  * return tm.make_task_packaged([=]() -> double {
278  * if (nums.empty()) return 0.0;
279  * return std::accumulate(nums.begin(), nums.end(), 0.0)/nums.size();
280  * });
281  * }
282  *
283  * // ... other calculation methods here
284  * };
285  *
286  * int main () {
287  *
288  * g_thread_init(0);
289  * Calcs calcs;
290  * auto res1 = calcs.mean({1, 2, 8, 0});
291  * auto res2 = calcs.mean({101, 53.7, 87, 1.2});
292  *
293  * // ... do something else
294  * std::cout << res1.get() << std::endl;
295  * std::cout << res2.get() << std::endl;
296  *
297  * }
298  * @endcode
299  *
300  * Here is a reimplementation, using TaskManager::make_task_when(), of
301  * the example using a get_primes() function given in the
302  * documentation for Cgu::Thread::Future:
303  * @code
304  * std::vector<long> get_primes(int n); // calculates the first n primes
305  *
306  * // get the first 1,000 primes
307  * using namespace Cgu;
308  *
309  * Thread::TaskManager tm;
310  * tm.make_task_when([] (const std::vector<long>& result) {
311  * for (const auto& elt: result) {std::cout << elt << std::endl;}
312  * },
313  * 0, // default main loop context
314  * [] () {return get_primes(1000);});
315  * @endcode
316  *
317  * Where a task running on a TaskManager object is to block, the
318  * TaskManager::IncHandle scoped handle class can be used to increment
319  * the maximum number of threads running on the object's thread pool
320  * temporarily while blocking takes place, so as to enable another
321  * thread to keep a core active. This can be useful where a task is
322  * to 'join' on another task when composing tasks: and it is usually
323  * essential to increment the maximum thread count temporarily where a
324  * task is to block on one of its sub-tasks, to avoid any possibility
325  * of deadlock through thread starvation (thread starvation occurs
326  * where all threads on a thread pool are occupied by tasks blocking
327  * on sub-tasks which have still to run on the thread pool, and which
328  * cannot run because the maximum thread count has been reached).
329  * Here is a compilable example:
330  *
331  * @code
332  * #include <iostream>
333  * #include <ostream>
334  *
335  * #include <glib.h>
336  *
337  * #include <c++-gtk-utils/task_manager.h>
338  *
339  * using namespace Cgu;
340  *
341  * // simulate a blocking operation, say from a server, with g_usleep()
342  * int mult(int x, int y) {
343  * g_usleep(100000);
344  * return x * y;
345  * }
346  *
347  * int main(int argc, char* argv[]) {
348  *
349  * g_thread_init(0);
350  * Thread::TaskManager tm{1}; // only one thread available unless blocking!
351  * GMainLoop* loop = g_main_loop_new(0, true);
352  *
353  * tm.make_task_when(
354  * [loop] (const int& res) {
355  * std::cout << res << std::endl;
356  * g_main_loop_quit(loop);
357  * },
358  * 0, // default main loop
359  * [&tm] () -> int {
360  * // this task multiplies 'a' by 2 and 'b' by 3, and adds the products
361  * int a = 10;
362  * int b = 12;
363  *
364  * // increment maximum thread count before launching sub-task and
365  * // then blocking
366  * Thread::TaskManager::IncHandle h{tm};
367  * // start a sub-task
368  * auto sub = tm.make_task_result([a, &tm] () -> int {
369  * // increment maximum thread count again before blocking in
370  * // this task (pretend that some other task in the program
371  * // may also want to run while both the parent task and this
372  * // task block on mult())
373  * Thread::TaskManager::IncHandle h{tm};
374  * return mult(a, 2);
375  * });
376  *
377  * int res = mult(b, 3)
378  * return sub->get() + res;
379  * }
380  * );
381  *
382  * g_main_loop_run(loop);
383  * }
384  * @endcode
385  *
386  * An alternative to using TaskManager::IncHandle for sub-tasks is to
387  * run the sub-tasks on their own threads via Thread::Future or
388  * std::async().
389  *
390  * Rate limiting
391  * -------------
392  *
393  * Resources are not infinite and there is a hard limit to the number
394  * of tasks that a TaskManager object may have queued for execution at
395  * any one time. From version 2.2.14 the limit to the number of
396  * running and queued tasks may be obtained by calling the
397  * TaskManager::get_max_tasks() method (note that particularly on
398  * 32-bit systems it will in practice be impossible to reach this
399  * limit because of memory exhaustion: the value returned by that
400  * method represents the limit enforced by TaskManager irrespective of
401  * the actual available memory at the system or process level and any
402  * intervention of std::bad_alloc exceptions). If that limit is
403  * exceeded, the TaskManager::add_task() and TaskManager::make_task_*
404  * methods will throw std::length_error.
405  *
406  * In practice however, on most systems such a large number of queued
407  * tasks (normally around 4,294,967,295 for 64-bit systems) is likely
408  * to be unfeasible and program logic constraints will be exceeded
409  * long before the limit is reached, even if available memory is not.
410  * In some usages therefore, some form of rate limiting may be needed
411  * to prevent a work-producing thread overwhelming a TaskManager
412  * object by continuously adding more tasks for execution than the
413  * object's throughput capacity is capable of dealing with, so pushing
414  * the number of unexecuted tasks to an excessive level.
415  *
416  * TaskManager objects provide no built-in rate limiting (other than
417  * throwing the std::length_error exception referred to above). This
418  * is because there is no one-size-fits-all way of doing so. One
419  * common approach is to apply throttling to threads which add tasks
420  * by enforcing a wait in their thread of execution when the level of
421  * queued tasks reaches too high a level, so hindering their ability
422  * to add new ones. However this is counter productive where it is a
423  * task running on the TaskManager object which is adding the new
424  * tasks, particularly with a TaskManager object having only a few
425  * threads running in its pool. Another approach is to throw an
426  * exception when adding tasks which exceed a user-selectable level
427  * which is much lower than the value returned by
428  * TaskManager::get_max_tasks(), but this would make it more difficult
429  * to use the Cgu::Thread::parallel_for_each() and
430  * Cgu::Thread::parallel_transform() functions provided by this
431  * library.
432  *
433  * The best approach is for user code to provide its own rate limiting
434  * in cases where the way that that code is organised means that it
435  * could produce an excessive number of accumulating unexecuted tasks,
436  * possibly by applying delays when unexecuted tasks rise in number
437  * excessively, using timeouts with a glib main loop. This may be
438  * checked for by having code call the TaskManager::get_tasks() method
439  * before adding a significant batch of new tasks in order to test
440  * queue size, and if necessary postpone adding the new tasks until
441  * the size of the already accumulated tasks has reduced.
442  *
443  * The Cgu::AsyncChannel class has emplace() and push() methods which
444  * will block when a channel is full. That class can therefore be
445  * used for rate limiting function objects pushed onto the channel in
446  * cases where that is an appropriate alternative solution to
447  * TaskManager.
448  */
449 
450 // TODO: this is a work-around for gcc < 4.7, which has a bug which
451 // requires a function whose return value is determined by decltype,
452 // such as make_task_result(Func&&), to be inline. At a suitable
453 // API/ABI break when gcc requirements are updated, this should be
454 // moved to task_manager.tpp.
455 namespace TaskManagerHelper2 {
456 
457 template <class Ret, class FType>
459  static void exec(FType& f,
460  const SharedLockPtr<AsyncResult<Ret>>& ret) {
461  ret->set(f());
462  }
463  static void do_fail(const SharedLockPtr<AsyncResult<Ret>>& ret) {
464  ret->set_error(); // won't throw
465  }
466 };
467 
468 /*
469  * The FunctorResultExec class is a specialised class which is
470  * necessary because the 'functor' member needs to be declared mutable
471  * so that it can bind to the reference to non-const argument of
472  * FunctorResultWrapper::exec(), and thus so that a mutable lambda can
473  * be executed by that function. Because it is so specialised, it is
474  * not suitable for inclusion in the generic interfaces provided in
475  * callback.h. (Except in this specialised usage, it can also be
476  * dangerous, as it allows a member of the callback object to be
477  * mutated: normally this would be undesirable.) An alternative would
478  * have been to put the 'functor' member in a wrapper struct like
479  * MemfunWhenWrapperArgs or FunWhenWrapperArgs, but if 'functor' were
480  * an lvalue that would mean it being copied twice. This is the most
481  * efficient implementation.
482  */
483 template <class Ret, class FType>
485  mutable FType functor;
487 public:
488  void dispatch() const {FunctorResultWrapper<Ret, FType>::exec(functor, ret);}
489  // we don't need to templatize 'ret_' for perfect forwarding - it is
490  // always passed as a lvalue
491  template <class FunctorArg>
492  FunctorResultExec(FunctorArg&& functor_,
493  const SharedLockPtr<AsyncResult<Ret>>& ret_): functor(std::forward<FunctorArg>(functor_)),
494  ret(ret_) {}
495 };
496 
497 } // namespace TaskManagerHelper2
498 
499 
500 class TaskManager {
501  public:
503  class IncHandle;
504  private:
505  typedef std::pair<std::unique_ptr<const Callback::Callback>,
506  std::unique_ptr<const Callback::Callback>> QueueItemType;
507 
508  struct RefImpl; // reference counted implementation class
509  // it is fine holding RefImpl by plain pointer and not by
510  // IntrusivePtr: it is the only data member this class has, so it
511  // can safely manage that member in its own destructor and other
512  // methods
513  RefImpl* ref_impl;
514 
515  void set_max_threads_impl(unsigned int max, Mutex::TrackLock& lock);
516  static unsigned int init_max_tasks();
517  public:
518 /**
519  * This class cannot be copied. The copy constructor is deleted.
520  */
521  TaskManager(const TaskManager&) = delete;
522 
523 /**
524  * This class cannot be copied. The assignment operator is deleted.
525  */
526  TaskManager& operator=(const TaskManager&) = delete;
527 
528  /**
529  * Gets the maximum number of threads which the TaskManager object is
530  * currently set to run in the thread pool. This value is established
531  * initially by the 'max' argument passed to the TaskManager
532  * constructor and can subequently be changed by calling
533  * set_max_threads() or change_max_threads(). The default value is 8.
534  * This method will not throw and is thread safe. However, if a
535  * blocking task might use the TaskManager::IncHandle class (or
536  * increase and then decrease the number by hand by calling
537  * change_max_threads()), this method will not usually be useful.
538  * @return The maximum number of threads.
539  *
540  * Since 2.0.12
541  */
542  unsigned int get_max_threads() const;
543 
544  /**
545  * Gets the minimum number of threads which the TaskManager object
546  * will run in the thread pool (these threads will last until
547  * stop_all() is called or the TaskManager object is destroyed).
548  * This value is established by the 'min' argument passed to the
549  * TaskManager constructor and cannot subequently be changed. The
550  * default is 0. This method will not throw and is thread safe.
551  * @return The minimum number of threads.
552  *
553  * Since 2.0.12
554  */
555  unsigned int get_min_threads() const;
556 
557  /**
558  * Gets the number of threads which the TaskManager object is
559  * currently running in the thread pool, including those blocking
560  * waiting for a task. This value could be greater than the number
561  * returned by get_max_threads() if change_max_threads() has recently
562  * been called with a negative number but not enough tasks have since
563  * completed to reduce the number of running threads to the new value
564  * set. This method will not throw and is thread safe.
565  * @return The number of threads running in the thread pool,
566  * including those blocking waiting for a task.
567  *
568  * Since 2.0.12
569  */
570  unsigned int get_used_threads() const;
571 
572  /**
573  * @deprecated
574  *
575  * DEPRECATED. Use change_max_threads() instead. This method will
576  * interfere with the intended operation of the
577  * ThreadManager::IncHandle class if one task constructs a IncHandle
578  * object and another calls this method.
579  *
580  * Sets the maximum number of threads which the TaskManager object
581  * will currently run in the thread pool. If this is less than the
582  * current number of running threads, the number of threads actually
583  * running will only be reduced as tasks complete, or as idle
584  * timeouts expire. This method does nothing if stop_all() has
585  * previously been called. This method is thread safe.
586  * @param max The maximum number of threads which the TaskManager
587  * object will currently run in the thread pool. This method will
588  * not set the maximum value of threads to a value less than that
589  * returned by get_min_threads(), nor to a value less than 1.
590  * @exception std::bad_alloc If this call is passed a value for 'max'
591  * which increases the maximum number of threads from its previous
592  * setting and tasks are currently queued for execution, new threads
593  * will be started for the queued tasks, so this exception may be
594  * thrown on starting the new threads if memory is exhausted and the
595  * system throws in that case. (On systems with
596  * over-commit/lazy-commit combined with virtual memory (swap), it is
597  * rarely useful to check for memory exhaustion).
598  * @exception Cgu::Thread::TaskError If this call is passed a value
599  * for 'max' which increases the maximum number of threads from its
600  * previous setting and tasks are currently queued for execution, new
601  * threads will be started for the queued tasks, so this exception
602  * may be thrown on starting the new threads if a thread fails to
603  * start correctly (this would mean that memory is exhausted, the
604  * pthread thread limit has been reached or pthread has run out of
605  * other resources to start new threads).
606  *
607  * Since 2.0.12
608  */
609  void set_max_threads(unsigned int max);
610 
611  /**
612  * This will increase, or if 'delta' is negative reduce, the maximum
613  * number of threads which the TaskManager object will currently run
614  * in the thread pool by the value of 'delta'. The purpose of this
615  * is to enable a task to increment the maximum thread number where
616  * it is about to enter a call which may block for some time, with a
617  * view to decrementing it later when it has finished making blocking
618  * calls, so as to enable another thread to keep a core active. If
619  * 'delta' is negative and results in a max_threads value of less
620  * than the current number of running threads, the number of threads
621  * actually running will only be reduced as tasks complete, or as
622  * idle timeouts expire. This method does nothing if stop_all() has
623  * previously been called. This method is thread safe. Since
624  * version 2.2.1, the scoped handle class TaskManager::IncHandle is
625  * available which calls this method.
626  * @param delta The change (positive or negative) to the maximum
627  * number of threads which the TaskManager object will currently run
628  * in the thread pool. This method will not set the maximum value of
629  * threads to a value less than that returned by get_min_threads(),
630  * nor to a value less than 1.
631  * @exception std::bad_alloc If this call is passed a positive value
632  * and tasks are currently queued for execution, a new thread or
633  * threads will be started for the queued tasks, so this exception
634  * may be thrown on starting a new thread if memory is exhausted and
635  * the system throws in that case. (On systems with
636  * over-commit/lazy-commit combined with virtual memory (swap), it is
637  * rarely useful to check for memory exhaustion).
638  * @exception Cgu::Thread::TaskError If this call is passed a
639  * positive value and tasks are currently queued for execution, a new
640  * thread or threads will be started for the queued tasks, so this
641  * exception may be thrown on starting a new thread if it fails to
642  * start correctly (this would mean that memory is exhausted, the
643  * pthread thread limit has been reached or pthread has run out of
644  * other resources to start new threads).
645  *
646  * Since 2.0.14
647  */
648  void change_max_threads(int delta);
649 
650  /**
651  * Gets the number of tasks which the TaskManager object is at
652  * present either running in the thread pool or has queued for
653  * execution. This value will be less than the number returned by
654  * get_used_threads() if threads in the thread pool are currently
655  * waiting to receive tasks for execution. This method will not
656  * throw and is thread safe.
657  * @return The number of tasks either running or queued for
658  * execution.
659  *
660  * Since 2.0.12
661  */
662  unsigned int get_tasks() const;
663 
664  /**
665  * Gets the limit to the sum of the number of tasks which a
666  * TaskManager object may have running in the thread pool or queued
667  * for execution at any one time. On a 32-bit system, reaching this
668  * limit will normally cause the amount of memory which any process
669  * may allocate to be exceeded so the limit will in practice never be
670  * met (the add_task() or make_task_* methods will throw a
671  * std::bad_alloc exception before then). On a 64-bit system this
672  * limit will normally be the same as UINT_MAX (4,294,967,295 for a
673  * 32-bit unsigned int) which although likely to be unfeasibly large
674  * could in theory be reached with a system which can make around
675  * 70GB of memory available to the process for the TaskManager
676  * object. The add_task() and make_task_* methods will throw
677  * std::length_error if an attempt is made to exceed this limit and
678  * std::bad_alloc has not got there first.
679  *
680  * This method is thread safe.
681  *
682  * @return The maximum number of tasks which a TaskManager object may
683  * have either running or queued for execution at any one time.
684  * @exception std::bad_alloc This exception may be thrown the first
685  * time this method is called. Any subsequent calls will not throw
686  * if an earlier one did not (this method calculates the limit once
687  * only and then caches it using static local initialization).
688  *
689  * Since 2.0.31 and 2.2.14
690  */
691  static unsigned int get_max_tasks() {
692  // having max_tasks as a local static rather than a namespace
693  // static means that we cannot suffer from the static
694  // initialization order fiasco. Static local initialization is
695  // also guaranteed to be thread safe in C++11 on. Because this
696  // function just calls up a local static, we might as well make it
697  // inline.
698  static unsigned int max_tasks = init_max_tasks();
699  return max_tasks;
700  }
701 
702  /**
703  * Gets the length of time in milliseconds that threads greater in
704  * number than the minimum and not executing any tasks will remain in
705  * existence waiting for new tasks. This value is established
706  * initially by the 'idle' argument passed to the TaskManager
707  * constructor and can subequently be changed by calling
708  * set_idle_time(). The default value is 10000 (10 seconds). This
709  * method will not throw and is thread safe.
710  * @return The idle time in milliseconds.
711  *
712  * Since 2.0.12
713  */
714  unsigned int get_idle_time() const;
715 
716  /**
717  * Sets the length of time in milliseconds that threads greater in
718  * number than the minimum and not executing any tasks will remain in
719  * existence waiting for new tasks. This will only have effect for
720  * threads in the pool which begin waiting for new tasks after this
721  * method is called. This method will not throw and is thread safe.
722  * @param idle The length of the idle time in milliseconds during
723  * which threads will remain waiting for new tasks.
724  *
725  * Since 2.0.12
726  */
727  void set_idle_time(unsigned int idle);
728 
729  /**
730  * Gets the current blocking setting, which determines whether calls
731  * to stop_all() and the destructor will block waiting for all
732  * remaining tasks to complete. This value is established initially
733  * by the 'blocking' argument passed to the TaskManager constructor
734  * and can subequently be changed by calling set_blocking(). This
735  * method will not throw and is thread safe.
736  * @return The current blocking setting.
737  *
738  * Since 2.0.12
739  */
740  bool get_blocking() const;
741 
742  /**
743  * Sets the current blocking setting, which determines whether calls
744  * to stop_all() and the destructor will block waiting for all
745  * remaining tasks to complete. This method cannot be called after
746  * stop_all() has been called (if that is attempted,
747  * Cgu::Thread::TaskError will be thrown). It is thread safe.
748  * @param blocking The new blocking setting.
749  * @exception Cgu::Thread::TaskError This exception will be thrown if
750  * stop_all() has previously been called.
751  *
752  * Since 2.0.12
753  */
754  void set_blocking(bool blocking);
755 
756  /**
757  * Gets the current StopMode setting (either
758  * Cgu::Thread::TaskManager::wait_for_running or
759  * Cgu::Thread::TaskManager::wait_for_all) executed when running
760  * stop_all() or when the destructor is called. See the
761  * documentation on stop_all() for an explanation of the setting.
762  * This value is established initially by the 'mode' argument passed
763  * to the TaskManager constructor and can subequently be changed by
764  * calling set_stop_mode(). This method will not throw and is thread
765  * safe.
766  * @return The current StopMode setting.
767  *
768  * Since 2.0.12
769  */
770  StopMode get_stop_mode() const;
771 
772  /**
773  * Sets the current StopMode setting (either
774  * Cgu::Thread::TaskManager::wait_for_running or
775  * Cgu::Thread::TaskManager::wait_for_all) executed when running
776  * stop_all() or when the destructor is called. See the
777  * documentation on stop_all() for an explanation of the setting.
778  * This method will not throw and is thread safe.
779  * @param mode The new StopMode setting.
780  *
781  * Since 2.0.12
782  */
783  void set_stop_mode(StopMode mode);
784 
785  /**
786  * This will cause the TaskManager object to stop running tasks. The
787  * precise effect depends on the current StopMode and blocking
788  * settings. If StopMode is set to
789  * Cgu::Thread::TaskManager::wait_for_running, all queued tasks which
790  * are not yet running on a thread will be dispensed with, but any
791  * already running will be left to complete normally. If StopMode is
792  * set to Cgu::Thread::TaskManager::wait_for_all, both already
793  * running tasks and all tasks already queued will be permitted to
794  * execute and complete normally. If the blocking setting is set to
795  * true, this method will wait until all the tasks still to execute
796  * have finished before returning, and if false it will return
797  * straight away.
798  *
799  * The StopMode setting should not be set to
800  * Cgu::Thread::TaskManager::wait_for_running if, when this method is
801  * called, another thread may be waiting on the get() or move_get()
802  * method of a Cgu::AsyncResult object returned by
803  * Cgu::Thread::TaskManager::make_task_result(), as otherwise that
804  * wait may never end - choose the
805  * Cgu::Thread::TaskManager::wait_for_all setting instead in such
806  * cases. This restriction does not apply to a thread waiting on a
807  * std::future object returned by
808  * Cgu::Thread::TaskManager::make_task_packaged(): instead
809  * std::future::get() will unblock and throw an exception upon the
810  * associated std::packaged_task object being destroyed as unexecuted
811  * queued tasks are dispensed with.
812  *
813  * After this method has been called, any attempt to add further
814  * tasks with the add_task() method will fail, and add_task() will
815  * throw Cgu::Thread::TaskError.
816  *
817  * This method is thread safe (any thread may call it) unless the
818  * blocking setting is true, in which case no task running on the
819  * TaskManager object may call this method.
820  *
821  * @exception std::bad_alloc This exception will be thrown if memory
822  * is exhausted and the system throws in that case. (On systems with
823  * over-commit/lazy-commit combined with virtual memory (swap), it is
824  * rarely useful to check for memory exhaustion).
825  * @exception Cgu::Thread::TaskError This exception will be thrown if
826  * stop_all() has previously been called, unless that previous call
827  * threw std::bad_alloc: if std::bad_alloc is thrown, this method may
828  * be called again to stop all threads, once the memory deficiency is
829  * dealt with, but no other methods of the TaskManager object should
830  * be called.
831  *
832  * Since 2.0.12
833  */
834  void stop_all();
835 
836  /**
837  * This method adds a new task. If one or more threads in the pool
838  * are currently blocking and waiting for a task, then the task will
839  * begin executing immediately in one of the threads. If not, and
840  * the value returned by get_used_threads() is less than the value
841  * returned by get_max_threads(), a new thread will start and the
842  * task will execute immediately in the new thread. Otherwise, the
843  * task will be queued for execution as soon as a thread becomes
844  * available. Tasks will be executed in the order in which they are
845  * added to the ThreadManager object. This method is thread safe
846  * (any thread may call it, including any task running on the
847  * TaskManager object).
848  *
849  * A task may terminate itself prematurely by throwing
850  * Cgu::Thread::Exit. In addition, the implementation of TaskManager
851  * will consume any other exception escaping from the task callback
852  * and safely terminate the task concerned in order to protect the
853  * integrity of the TaskManager object. Where detecting any of these
854  * outcomes is important (usually it won't be), the two argument
855  * version of this method is available so that a 'fail' callback can
856  * be executed in these circumstances.
857  *
858  * @param task A callback representing the new task, as constructed
859  * by the Callback::lambda(), Callback::make() or
860  * Callback::make_ref() factory functions. Ownership is taken of
861  * this callback, and it will be disposed of when it has been
862  * finished with. If an exception propagates from the task, the
863  * exception will be consumed and (if the thrown object's type is not
864  * Cgu::Thread::Exit) a g_critical() warning will be issued. The
865  * destructors of any bound arguments in the callback must not throw.
866  * @exception std::bad_alloc This exception will be thrown if memory
867  * is exhausted and the system throws in that case. (On systems with
868  * over-commit/lazy-commit combined with virtual memory (swap), it is
869  * rarely useful to check for memory exhaustion). See also the
870  * documentation for the get_max_tasks() method about the possibility
871  * of std::length_error being thrown. If std::bad_alloc or
872  * std::length_error is thrown, the task will not start and the
873  * 'task' callback will be disposed of.
874  * @exception Cgu::Thread::TaskError This exception will be thrown if
875  * stop_all() has previously been called. It will also be thrown if
876  * is_error() would return true because this class's internal thread
877  * pool loop implementation has thrown std::bad_alloc, or a thread
878  * has failed to start correctly. (On systems with
879  * over-commit/lazy-commit combined with virtual memory (swap), it is
880  * rarely useful to check for memory exhaustion, but there may be
881  * some specialized cases where the return value of is_error() is
882  * useful.) If this exception is thrown, the task will not start and
883  * the 'task' callback will be disposed of.
884  *
885  * Since 2.0.12
886  */
887  void add_task(const Callback::Callback* task) {
888  add_task(std::unique_ptr<const Callback::Callback>(task),
889  std::unique_ptr<const Callback::Callback>());
890  }
891 
892  /**
893  * This method adds a new task. If one or more threads in the pool
894  * are currently blocking and waiting for a task, then the task will
895  * begin executing immediately in one of the threads. If not, and
896  * the value returned by get_used_threads() is less than the value
897  * returned by get_max_threads(), a new thread will start and the
898  * task will execute immediately in the new thread. Otherwise, the
899  * task will be queued for execution as soon as a thread becomes
900  * available. Tasks will be executed in the order in which they are
901  * added to the ThreadManager object. This method is thread safe
902  * (any thread may call it, including any task running on the
903  * TaskManager object).
904  *
905  * A task may terminate itself prematurely by throwing
906  * Cgu::Thread::Exit. In addition, the implementation of TaskManager
907  * will consume any other exception escaping from the task callback
908  * and safely terminate the task concerned in order to protect the
909  * integrity of the TaskManager object. Where detecting any of these
910  * outcomes is important (usually it won't be), a callback can be
911  * passed to the 'fail' argument which will execute if, and only if,
912  * either Cgu::Thread::Exit is thrown or some other exception has
913  * propagated from the task. This 'fail' callback is different from
914  * the 'fail' callback of Cgu::Thread::Future objects (programming
915  * for many tasks to a lesser number of threads requires different
916  * approaches from programming for one thread per task), and it
917  * executes in the task thread rather than executing in a glib main
918  * loop (however, the 'fail' callback can of course call
919  * Cgu::Callback::post() to execute another callback in a main loop,
920  * if that is what is wanted).
921  *
922  * @param task A callback representing the new task, as constructed
923  * by the Callback::lambda(), Callback::make() or
924  * Callback::make_ref() factory functions. If an exception
925  * propagates from the task, the exception will be consumed and the
926  * 'fail' callback will execute.
927  * @param fail A callback (as constructed by the Callback::lambda(),
928  * Callback::make() or Callback::make_ref() factory functions) which
929  * will be executed if the function or callable object executed by
930  * the 'task' callback exits by throwing Thread::Exit or some other
931  * exception. If an exception propagates from the 'fail' callback,
932  * this will be consumed to protect the TaskManager object, and a
933  * g_critical() warning will be issued.
934  * @exception std::bad_alloc This exception will be thrown if memory
935  * is exhausted and the system throws in that case. (On systems with
936  * over-commit/lazy-commit combined with virtual memory (swap), it is
937  * rarely useful to check for memory exhaustion). See also the
938  * documentation for the get_max_tasks() method about the possibility
939  * of std::length_error being thrown. If std::bad_alloc or
940  * std::length_error is thrown, the task will not start (which also
941  * means that the 'fail' callback will not execute).
942  * @exception Cgu::Thread::TaskError This exception will be thrown if
943  * stop_all() has previously been called. It will also be thrown if
944  * is_error() would return true because this class's internal thread
945  * pool loop implementation has thrown std::bad_alloc, or a thread
946  * has failed to start correctly. (On systems with
947  * over-commit/lazy-commit combined with virtual memory (swap), it is
948  * rarely useful to check for memory exhaustion, but there may be
949  * some specialized cases where the return value of is_error() is
950  * useful.) If this exception is thrown, the task will not start
951  * (which also means that the 'fail' callback will not execute).
952  *
953  * Since 2.0.12
954  */
955  void add_task(std::unique_ptr<const Callback::Callback> task,
956  std::unique_ptr<const Callback::Callback> fail);
957 
958  /**
959  * This method adds a new task. If one or more threads in the pool
960  * are currently blocking and waiting for a task, then the task will
961  * begin executing immediately in one of the threads. If not, and
962  * the value returned by get_used_threads() is less than the value
963  * returned by get_max_threads(), a new thread will start and the
964  * task will execute immediately in the new thread. Otherwise, the
965  * task will be queued for execution as soon as a thread becomes
966  * available. Tasks will be executed in the order in which they are
967  * added to the ThreadManager object. This method is thread safe
968  * (any thread may call it, including any task running on the
969  * TaskManager object).
970  *
971  * A task may terminate itself prematurely by throwing
972  * Cgu::Thread::Exit. In addition, the implementation of TaskManager
973  * will consume any other exception escaping from the task callback
974  * and safely terminate the task concerned in order to protect the
975  * integrity of the TaskManager object. Where detecting any of these
976  * outcomes is important (usually it won't be), the two argument
977  * version of this method is available so that a 'fail' callback can
978  * be executed in these circumstances.
979  *
980  * @param task A callable object representing the new task, such as
981  * formed by a lambda expression or the result of std::bind. It must
982  * be fully bound (that is, it must take no arguments when called).
983  * If an exception propagates from the task, the exception will be
984  * consumed and (if the thrown object's type is not
985  * Cgu::Thread::Exit) a g_critical() warning will be issued. The
986  * destructors of any bound values must not throw.
987  * @exception std::bad_alloc This exception will be thrown if memory
988  * is exhausted and the system throws in that case. (On systems with
989  * over-commit/lazy-commit combined with virtual memory (swap), it is
990  * rarely useful to check for memory exhaustion). See also the
991  * documentation for the get_max_tasks() method about the possibility
992  * of std::length_error being thrown. If std::bad_alloc or
993  * std::length_error is thrown, the task will not start.
994  * @exception Cgu::Thread::TaskError This exception will be thrown if
995  * stop_all() has previously been called. It will also be thrown if
996  * is_error() would return true because this class's internal thread
997  * pool loop implementation has thrown std::bad_alloc, or a thread
998  * has failed to start correctly. (On systems with
999  * over-commit/lazy-commit combined with virtual memory (swap), it is
1000  * rarely useful to check for memory exhaustion, but there may be
1001  * some specialized cases where the return value of is_error() is
1002  * useful.) If this exception is thrown, the task will not start.
1003  * @note An exception might also be thrown if the copy or move
1004  * constructor of the callable object throws. If such an exception
1005  * is thrown, the task will not start.
1006  *
1007  * Since 2.1.0
1008  */
1009  // we need to use enable_if so that where this function is passed a
1010  // pointer to non-const Callback::Callback, or some other
1011  // convertible pointer, this templated overload is dropped from the
1012  // overload set, in order to support the Callback::Callback
1013  // overloads of this function. This overload calls into the version
1014  // of this function taking a pointer to const Callback::Callback in
1015  // order to perform type erasure.
1016  template <class Task,
1017  class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<Task>::type,
1018  const Callback::Callback*>::value>::type>
1019  void add_task(Task&& task) {
1020  add_task(std::unique_ptr<const Callback::Callback>(Callback::lambda<>(std::forward<Task>(task))),
1021  std::unique_ptr<const Callback::Callback>());
1022  }
1023 
1024  /**
1025  * This method adds a new task. If one or more threads in the pool
1026  * are currently blocking and waiting for a task, then the task will
1027  * begin executing immediately in one of the threads. If not, and
1028  * the value returned by get_used_threads() is less than the value
1029  * returned by get_max_threads(), a new thread will start and the
1030  * task will execute immediately in the new thread. Otherwise, the
1031  * task will be queued for execution as soon as a thread becomes
1032  * available. Tasks will be executed in the order in which they are
1033  * added to the ThreadManager object. This method is thread safe
1034  * (any thread may call it, including any task running on the
1035  * TaskManager object).
1036  *
1037  * A task may terminate itself prematurely by throwing
1038  * Cgu::Thread::Exit. In addition, the implementation of TaskManager
1039  * will consume any other exception escaping from the task callback
1040  * and safely terminate the task concerned in order to protect the
1041  * integrity of the TaskManager object. Where detecting any of these
1042  * outcomes is important (usually it won't be), a callback can be
1043  * passed to the 'fail' argument which will execute if, and only if,
1044  * either Cgu::Thread::Exit is thrown or some other exception has
1045  * propagated from the task. This 'fail' callback is different from
1046  * the 'fail' callback of Cgu::Thread::Future objects (programming
1047  * for many tasks to a lesser number of threads requires different
1048  * approaches from programming for one thread per task), and it
1049  * executes in the task thread rather than executing in a glib main
1050  * loop (however, the 'fail' callback can of course call
1051  * Cgu::Callback::post() to execute another callback in a main loop,
1052  * if that is what is wanted).
1053  *
1054  * @param task A callable object representing the new task, such as
1055  * formed by a lambda expression or the result of std::bind. It must
1056  * be fully bound (that is, it must take no arguments when called).
1057  * The destructors of any bound values must not throw. If an exception
1058  * propagates from the task, the exception will be consumed and the
1059  * 'fail' callback will execute.
1060  * @param fail A callable object (such as formed by a lambda
1061  * expression or the result of std::bind) which will be executed if
1062  * the callable object represented by the 'task' callback exits by
1063  * throwing Thread::Exit or some other exception. It must be fully
1064  * bound (that is, it must take no arguments when called). The
1065  * destructors of any bound values must not throw. If an exception
1066  * propagates from the 'fail' callback, this will be consumed to
1067  * protect the TaskManager object, and a g_critical() warning will be
1068  * issued.
1069  * @exception std::bad_alloc This exception will be thrown if memory
1070  * is exhausted and the system throws in that case. (On systems with
1071  * over-commit/lazy-commit combined with virtual memory (swap), it is
1072  * rarely useful to check for memory exhaustion). See also the
1073  * documentation for the get_max_tasks() method about the possibility
1074  * of std::length_error being thrown. If std::bad_alloc or
1075  * std::length_error is thrown, the task will not start (which also
1076  * means that the 'fail' callback will not execute).
1077  * @exception Cgu::Thread::TaskError This exception will be thrown if
1078  * stop_all() has previously been called. It will also be thrown if
1079  * is_error() would return true because this class's internal thread
1080  * pool loop implementation has thrown std::bad_alloc, or a thread
1081  * has failed to start correctly. (On systems with
1082  * over-commit/lazy-commit combined with virtual memory (swap), it is
1083  * rarely useful to check for memory exhaustion, but there may be
1084  * some specialized cases where the return value of is_error() is
1085  * useful.) If this exception is thrown, the task will not start
1086  * (which also means that the 'fail' callback will not execute).
1087  * @note An exception might also be thrown if the copy or move
1088  * constructor of the 'task' or 'fail' callable objects throws. If
1089  * such an exception is thrown, the task will not start (which also
1090  * means that the 'fail' callback will not execute)
1091  *
1092  * Since 2.1.0
1093  */
1094  // we need to use enable_if so that where this function is passed
1095  // unique_ptr's holding non-const Callback::Callback objects, or
1096  // some other convertible object, this templated overload is dropped
1097  // from the overload set, in order to support the unique_ptr
1098  // overloads of this function. This overload calls into the version
1099  // of this function taking Callback objects by unique_ptr in order
1100  // to perform type erasure.
1101  template <class Task, class Fail,
1102  class = typename std::enable_if<!std::is_convertible<Task, std::unique_ptr<const Callback::Callback>>::value
1103  && !std::is_convertible<Fail, std::unique_ptr<const Callback::Callback>>::value>::type>
1104  void add_task(Task&& task, Fail&& fail) {
1105  std::unique_ptr<const Callback::Callback> task_cb(
1106  Callback::lambda<>(std::forward<Task>(task))
1107  );
1108  std::unique_ptr<const Callback::Callback> fail_cb(
1109  Callback::lambda<>(std::forward<Fail>(fail))
1110  );
1111  add_task(std::move(task_cb), std::move(fail_cb));
1112  }
1113 
1114  /**
1115  * This will return true if a thread required by the thread pool has
1116  * failed to start correctly because of memory exhaustion or because
1117  * pthread has run out of other resources to start new threads, or
1118  * because an internal operation has thrown std::bad_alloc. (On
1119  * systems with over-commit/lazy-commit combined with virtual memory
1120  * (swap), it is rarely useful to check for memory exhaustion, and
1121  * even more so where glib is used, as that terminates a program if
1122  * memory cannot be obtained from the operating system, but there may
1123  * be some specialized cases where the return value of this method is
1124  * useful - this class does not use any glib functions which might
1125  * cause such termination.) This method will not throw and is thread
1126  * safe.
1127  *
1128  * Since 2.0.12
1129  */
1130  bool is_error() const;
1131 
1132  /**
1133  * @deprecated
1134  *
1135  * DEPRECATED. Use the versions of make_task_result() which take
1136  * callable objects.
1137  *
1138  * This is a wrapper which takes a member function pointer to a
1139  * member function which returns a value, together with arguments,
1140  * and constructs a TaskManager task which will execute that function
1141  * by calling add_task() with an appropriate callback object, and
1142  * returns a Cgu::AsyncResult object (held by Cgu::SharedLockPtr)
1143  * which will provide the value that the function returns. Apart
1144  * from the absence of a 'one thread per task' model, this method
1145  * therefore provides a similar interface to the one provided by
1146  * Cgu::Thread::Future. It is thread safe: any thread may call this
1147  * method, including another task running on the TaskManager object,
1148  * but see the introductory remarks about the use of the
1149  * TaskManager::IncHandle scoped handle class where a task running on
1150  * a TaskManager object is to block on one of its sub-tasks. See
1151  * also the documentation on add_task() for further information about
1152  * how task execution works.
1153  *
1154  * This method can take up to three bound arguments for the target
1155  * member function.
1156  *
1157  * If the function passed to this method exits by throwing
1158  * Thread::Exit or some other exception, then the exception will be
1159  * consumed and the returned Cgu::AsyncResult object's get() or
1160  * move_get() method will unblock and its get_error() method will
1161  * return -1.
1162  *
1163  * @param t The object whose member function passed to this method is
1164  * to execute as a task.
1165  * @param func The member function to be executed as a task.
1166  * @param args The arguments to be passed to that member function.
1167  * @exception std::bad_alloc This exception will be thrown if memory
1168  * is exhausted and the system throws in that case. (On systems with
1169  * over-commit/lazy-commit combined with virtual memory (swap), it is
1170  * rarely useful to check for memory exhaustion). See also the
1171  * documentation for the get_max_tasks() method about the possibility
1172  * of std::length_error being thrown. If std::bad_alloc or
1173  * std::length_error is thrown, the task will not start.
1174  * @exception Cgu::Thread::TaskError This exception will be thrown if
1175  * stop_all() has previously been called. It will also be thrown if
1176  * is_error() would return true because this class's internal thread
1177  * pool loop implementation has thrown std::bad_alloc, or a thread
1178  * has failed to start correctly. (On systems with
1179  * over-commit/lazy-commit combined with virtual memory (swap), it is
1180  * rarely useful to check for memory exhaustion, but there may be
1181  * some specialized cases where the return value of is_error() is
1182  * useful.) If this exception is thrown, the task will not start.
1183  * @note This method will also throw if the copy or move constructor
1184  * of a bound argument throws. If such an exception is thrown, the
1185  * task will not start.
1186  *
1187  * Since 2.0.13
1188  */
1189 
1190  template <class Ret, class... Params, class... Args, class T>
1192  Ret (T::*func)(Params...),
1193  Args&&... args);
1194 
1195  /**
1196  * @deprecated
1197  *
1198  * DEPRECATED. Use the versions of make_task_when_full() which take
1199  * callable objects.
1200  *
1201  * This is a wrapper which takes a member function pointer to a
1202  * member function which returns a value, together with arguments,
1203  * and constructs a TaskManager task which will execute that function
1204  * by calling add_task() with an appropriate callback object, and
1205  * causes the 'when' callback passed as an argument to this method to
1206  * be executed by a glib main loop if and when the task finishes
1207  * correctly - the 'when' callback is passed the member function's
1208  * return value when it is invoked. It is thread safe (any thread
1209  * may call this method, including another task running on the
1210  * TaskManager object). Apart from the absence of a 'one thread per
1211  * task' model, this method therefore provides a similar interface to
1212  * the one provided by Cgu::Thread::Future. See the documentation on
1213  * add_task() for further information about how task execution works.
1214  *
1215  * This method can take up to three bound arguments for the target
1216  * member function.
1217  *
1218  * Note that unlike add_task(), but like the 'fail' callback of
1219  * Cgu::Thread::Future objects, if a fail callback is provided to
1220  * this method and it executes, it will execute in the glib main loop
1221  * whose GMainContext object is passed to the 'context' argument of
1222  * this method.
1223  *
1224  * Note also that if releasers are provided for the 'when' or 'fail'
1225  * callbacks, these are passed by pointer and not by reference (this
1226  * is so that a NULL pointer can indicate that no releaser is to be
1227  * provided). If provided, a releaser will enable automatic
1228  * disconnection of the 'when' or 'fail' callback, if the object
1229  * having the callback function as a member is destroyed. For this to
1230  * be race free, the lifetime of that object must be controlled by
1231  * the thread in whose main loop the 'when' or 'fail' callback will
1232  * execute.
1233  *
1234  * The make_task_when() method is similar to this method but provides
1235  * an abbreviated set of paramaters suitable for most cases. This
1236  * method is for use where releasers or a 'fail' callback are
1237  * required.
1238  *
1239  * @param when A callback which will be executed if and when the
1240  * function passed to this method finishes correctly. The callback is
1241  * passed that function's return value when it is invoked. If an
1242  * exception propagates from the 'when' callback, this will be
1243  * consumed and a g_critical() warning will be issued. The callback
1244  * will execute in the glib main loop whose GMainContext object is
1245  * passed to the 'context' argument of this method.
1246  * @param when_releaser A pointer to a Releaser object for automatic
1247  * disconnection of the 'when' callback before it executes in a main
1248  * loop (mainly relevant if the callback represents a non-static
1249  * member function of an object which may be destroyed before the
1250  * callback executes). A value of 0/NULL/nullptr indicates no
1251  * releaser.
1252  * @param fail A callback which will be executed if the 'when'
1253  * callback does not execute. This would happen if the function
1254  * passed to this method exits by throwing Thread::Exit or some other
1255  * exception, if the copy constructor of a non-reference argument of
1256  * that function throws, if the move constructor (or if it has none,
1257  * the copy constructor) of that function's return value throws or if
1258  * the 'when' callback does not execute because the internal
1259  * implementation of this wrapper throws std::bad_alloc (which will
1260  * not happen if the library has been installed using the
1261  * \--with-glib-memory-slices-no-compat configuration option: instead
1262  * glib will terminate the program if it is unable to obtain memory
1263  * from the operating system). If an exception propagates from the
1264  * 'fail' callback, this will be consumed and a g_critical() warning
1265  * will be issued. The callback will execute in the glib main loop
1266  * whose GMainContext object is passed to the 'context' argument of
1267  * this method. An empty std::unique_ptr object indicates no 'fail'
1268  * callback.
1269  * @param fail_releaser A pointer to a Releaser object for automatic
1270  * disconnection of the 'fail' callback before it executes in a main
1271  * loop (mainly relevant if the callback represents a non-static
1272  * member function of an object which may be destroyed before the
1273  * callback executes). A value of 0/NULL/nullptr indicates no
1274  * releaser.
1275  * @param priority The priority to be given in the main loop to the
1276  * 'when' callback or any 'fail' callback. In ascending order of
1277  * priorities, priorities are G_PRIORITY_LOW,
1278  * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1279  * and G_PRIORITY_HIGH. This determines the order in which the
1280  * callback will appear in the event list in the main loop, not the
1281  * priority which the OS will adopt.
1282  * @param context The glib main context of the main loop in which the
1283  * 'when' callback or any 'fail' callback is to be executed. A value
1284  * 0/NULL/nullptr will cause the callback to be executed in the main
1285  * program loop.
1286  * @param t The object whose member function passed to this method is
1287  * to execute as a task.
1288  * @param func The member function to be executed as a task. If an
1289  * exception propagates from the task, the exception will be consumed
1290  * and the 'fail' callback will execute.
1291  * @param args The arguments to be passed to that member function.
1292  * @exception std::bad_alloc This exception will be thrown if memory
1293  * is exhausted and the system throws in that case. (On systems with
1294  * over-commit/lazy-commit combined with virtual memory (swap), it is
1295  * rarely useful to check for memory exhaustion). See also the
1296  * documentation for the get_max_tasks() method about the possibility
1297  * of std::length_error being thrown. If std::bad_alloc or
1298  * std::length_error is thrown, the task will not start (which also
1299  * means that the 'when' and 'fail' callbacks will not execute).
1300  * @exception Cgu::Thread::TaskError This exception will be thrown if
1301  * stop_all() has previously been called. It will also be thrown if
1302  * is_error() would return true because this class's internal thread
1303  * pool loop implementation has thrown std::bad_alloc, or a thread
1304  * has failed to start correctly. (On systems with
1305  * over-commit/lazy-commit combined with virtual memory (swap), it is
1306  * rarely useful to check for memory exhaustion, but there may be
1307  * some specialized cases where the return value of is_error() is
1308  * useful.) If this exception is thrown, the task will not start
1309  * (which also means that the 'when' and 'fail' callbacks will not
1310  * execute).
1311  * @note 1. This method will also throw if the copy or move
1312  * constructor of a bound argument throws. If such an exception is
1313  * thrown, the task will not start (which also means that the 'when'
1314  * and 'fail' callbacks will not execute).
1315  * @note 2. If a 'when_releaser' or a 'fail_releaser' object is
1316  * provided, it is in theory possible (if memory is exhausted and the
1317  * system throws in that case) that an internal SafeEmitterArg object
1318  * will throw std::bad_alloc when emitting/executing the 'when' or
1319  * 'fail' callback in the glib main loop, with the result that the
1320  * relevant callback will not execute (instead the exception will be
1321  * consumed and a g_critical() warning will be issued). This is
1322  * rarely of any relevance because glib will abort the program if it
1323  * is itself unable to obtain memory from the operating system.
1324  * However, where it is relevant, design the program so that it is
1325  * not necessary to provide a releaser object.
1326  *
1327  * Since 2.0.13
1328  */
1329  template <class Ret, class... Params, class... Args, class T>
1330  void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1331  Cgu::Releaser* when_releaser,
1332  std::unique_ptr<const Cgu::Callback::Callback> fail,
1333  Cgu::Releaser* fail_releaser,
1334  gint priority,
1335  GMainContext* context,
1336  T& t,
1337  Ret (T::*func)(Params...),
1338  Args&&... args);
1339 
1340  /**
1341  * @deprecated
1342  *
1343  * DEPRECATED. Use the versions of make_task_when() which take
1344  * callable objects.
1345  *
1346  * This is an abbreviated version of make_task_when_full(), which is
1347  * for use when it is known that invocation of the member function
1348  * passed to this method, the copy constructors of any non-reference
1349  * arguments of that function and the move constructor (or if it has
1350  * none, the copy constructor) of that function's return value do not
1351  * throw anything other than std::bad_alloc, and the user is not
1352  * interested in std::bad_alloc and does not need a Cgu::Releaser
1353  * object for the 'when' callback (which is likely to cover the
1354  * majority of uses, particularly when composing tasks using glib
1355  * because glib terminates the program if it is unable to obtain
1356  * memory).
1357  *
1358  * This method can take up to three bound arguments for the target
1359  * member function.
1360  *
1361  * Like make_task_when_full(), this method is a wrapper which takes a
1362  * member function pointer to a member function which returns a
1363  * value, together with arguments, and constructs a TaskManager task
1364  * which will execute that function by calling add_task() with an
1365  * appropriate callback object, and causes the 'when' callback passed
1366  * as an argument to this method to be executed by a glib main loop
1367  * if and when the task finishes correctly - the 'when' callback is
1368  * passed the member function's return value when it is invoked. It
1369  * is thread safe (any thread may call this method, including another
1370  * task running on the TaskManager object). Apart from the absence
1371  * of a 'one thread per task' model, this method therefore provides a
1372  * similar interface to the one provided by Cgu::Thread::Future. See
1373  * the documentation on add_task() for further information about how
1374  * task execution works.
1375  *
1376  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
1377  * in the main loop.
1378  *
1379  * @param when A callback which will be executed if and when the
1380  * function passed to this method finishes correctly. The callback is
1381  * passed that function's return value when it is invoked. If an
1382  * exception propagates from the 'when' callback, this will be
1383  * consumed and a g_critical() warning will be issued. The callback
1384  * will execute in the glib main loop whose GMainContext object is
1385  * passed to the 'context' argument of this method.
1386  * @param context The glib main context of the main loop in which the
1387  * 'when' callback is to be executed. A value 0/NULL/nullptr will
1388  * cause the callback to be executed in the main program loop.
1389  * @param t The object whose member function passed to this method is
1390  * to execute as a task.
1391  * @param func The member function to be executed as a task. If an
1392  * exception propagates from the task, the exception will be consumed
1393  * and (if the thrown object's type is not Cgu::Thread::Exit) a
1394  * g_critical() warning will be issued.
1395  * @param args The arguments to be passed to that member function.
1396  * @exception std::bad_alloc This exception will be thrown if memory
1397  * is exhausted and the system throws in that case. (On systems with
1398  * over-commit/lazy-commit combined with virtual memory (swap), it is
1399  * rarely useful to check for memory exhaustion). See also the
1400  * documentation for the get_max_tasks() method about the possibility
1401  * of std::length_error being thrown. If std::bad_alloc or
1402  * std::length_error is thrown, the task will not start (which also
1403  * means that the 'when' callback will not execute).
1404  * @exception Cgu::Thread::TaskError This exception will be thrown if
1405  * stop_all() has previously been called. It will also be thrown if
1406  * is_error() would return true because this class's internal thread
1407  * pool loop implementation has thrown std::bad_alloc, or a thread
1408  * has failed to start correctly. (On systems with
1409  * over-commit/lazy-commit combined with virtual memory (swap), it is
1410  * rarely useful to check for memory exhaustion, but there may be
1411  * some specialized cases where the return value of is_error() is
1412  * useful.) If this exception is thrown, the task will not start
1413  * (which also means that the 'when' callback will not execute).
1414  * @note 1. This method will also throw if the copy or move
1415  * constructor of a bound argument throws. If such an exception is
1416  * thrown, the task will not start (which also means that the 'when'
1417  * callback will not execute).
1418  * @note 2. As mentioned in describing 'func' above, if 'func' exits
1419  * by throwing an exception the exception will be consumed and (if
1420  * the thrown object's type is not Cgu::Thread::Exit) a g_critical()
1421  * warning will be issued. The same will occur if the copy
1422  * constructor of a non-reference argument of 'func' throws when
1423  * invoking 'func' or the move constructor (or if it has none, the
1424  * copy constructor) of the return value of 'func' throws, or if the
1425  * internal implementation of this wrapper throws std::bad_alloc on
1426  * executing 'func'.
1427  *
1428  * Since 2.0.13
1429  */
1430  template <class Ret, class... Params, class... Args, class T>
1431  void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1432  GMainContext* context,
1433  T& t,
1434  Ret (T::*func)(Params...),
1435  Args&&... args) {
1436  static_assert(sizeof...(Args) < 4,
1437  "No greater than three bound arguments can be passed to "
1438  "TaskManager::make_task_when() taking a member function.");
1439 
1440  make_task_when_full(std::move(when),
1441  0,
1442  std::unique_ptr<const Cgu::Callback::Callback>(),
1443  0,
1444  G_PRIORITY_DEFAULT,
1445  context,
1446  t,
1447  func,
1448  std::forward<Args>(args)...);
1449  }
1450 
1451  /**
1452  * @deprecated
1453  *
1454  * DEPRECATED. Use the versions of make_task_result() which take
1455  * callable objects.
1456  *
1457  * This is a wrapper which takes a member function pointer to a
1458  * member function which returns a value, together with arguments,
1459  * and constructs a TaskManager task which will execute that function
1460  * by calling add_task() with an appropriate callback object, and
1461  * returns a Cgu::AsyncResult object (held by Cgu::SharedLockPtr)
1462  * which will provide the value that the function returns. Apart
1463  * from the absence of a 'one thread per task' model, this method
1464  * therefore provides a similar interface to the one provided by
1465  * Cgu::Thread::Future. It is thread safe: any thread may call this
1466  * method, including another task running on the TaskManager object,
1467  * but see the introductory remarks about the use of the
1468  * TaskManager::IncHandle scoped handle class where a task running on
1469  * a TaskManager object is to block on one of its sub-tasks. See
1470  * also the documentation on add_task() for further information about
1471  * how task execution works.
1472  *
1473  * This method can take up to three bound arguments for the target
1474  * member function.
1475  *
1476  * If the function passed to this method exits by throwing
1477  * Thread::Exit or some other exception, then the exception will be
1478  * consumed and the returned Cgu::AsyncResult object's get() or
1479  * move_get() method will unblock and its get_error() method will
1480  * return -1.
1481  *
1482  * @param t The object whose member function passed to this method is
1483  * to execute as a task.
1484  * @param func The member function to be executed as a task.
1485  * @param args The arguments to be passed to that member function.
1486  * @exception std::bad_alloc This exception will be thrown if memory
1487  * is exhausted and the system throws in that case. (On systems with
1488  * over-commit/lazy-commit combined with virtual memory (swap), it is
1489  * rarely useful to check for memory exhaustion). See also the
1490  * documentation for the get_max_tasks() method about the possibility
1491  * of std::length_error being thrown. If std::bad_alloc or
1492  * std::length_error is thrown, the task will not start.
1493  * @exception Cgu::Thread::TaskError This exception will be thrown if
1494  * stop_all() has previously been called. It will also be thrown if
1495  * is_error() would return true because this class's internal thread
1496  * pool loop implementation has thrown std::bad_alloc, or a thread
1497  * has failed to start correctly. (On systems with
1498  * over-commit/lazy-commit combined with virtual memory (swap), it is
1499  * rarely useful to check for memory exhaustion, but there may be
1500  * some specialized cases where the return value of is_error() is
1501  * useful.) If this exception is thrown, the task will not start.
1502  * @note This method will also throw if the copy or move constructor
1503  * of a bound argument throws. If such an exception is thrown, the
1504  * task will not start.
1505  *
1506  * Since 2.0.13
1507  */
1508 
1509  template <class Ret, class... Params, class... Args, class T>
1511  Ret (T::*func)(Params...) const,
1512  Args&&... args);
1513 
1514  /**
1515  * @deprecated
1516  *
1517  * DEPRECATED. Use the versions of make_task_when_full() which take
1518  * callable objects.
1519  *
1520  * This is a wrapper which takes a member function pointer to a
1521  * member function which returns a value, together with arguments,
1522  * and constructs a TaskManager task which will execute that function
1523  * by calling add_task() with an appropriate callback object, and
1524  * causes the 'when' callback passed as an argument to this method to
1525  * be executed by a glib main loop if and when the task finishes
1526  * correctly - the 'when' callback is passed the member function's
1527  * return value when it is invoked. It is thread safe (any thread
1528  * may call this method, including another task running on the
1529  * TaskManager object). Apart from the absence of a 'one thread per
1530  * task' model, this method therefore provides a similar interface to
1531  * the one provided by Cgu::Thread::Future. See the documentation on
1532  * add_task() for further information about how task execution works.
1533  *
1534  * This method can take up to three bound arguments for the target
1535  * member function.
1536  *
1537  * Note that unlike add_task(), but like the 'fail' callback of
1538  * Cgu::Thread::Future objects, if a fail callback is provided to
1539  * this method and it executes, it will execute in the glib main loop
1540  * whose GMainContext object is passed to the 'context' argument of
1541  * this method.
1542  *
1543  * Note also that if releasers are provided for the 'when' or 'fail'
1544  * callbacks, these are passed by pointer and not by reference (this
1545  * is so that a NULL pointer can indicate that no releaser is to be
1546  * provided). If provided, a releaser will enable automatic
1547  * disconnection of the 'when' or 'fail' callback, if the object
1548  * having the callback function as a member is destroyed. For this to
1549  * be race free, the lifetime of that object must be controlled by
1550  * the thread in whose main loop the 'when' or 'fail' callback will
1551  * execute.
1552  *
1553  * The make_task_when() method is similar to this method but provides
1554  * an abbreviated set of paramaters suitable for most cases. This
1555  * method is for use where releasers or a 'fail' callback are
1556  * required.
1557  *
1558  * @param when A callback which will be executed if and when the
1559  * function passed to this method finishes correctly. The callback is
1560  * passed that function's return value when it is invoked. If an
1561  * exception propagates from the 'when' callback, this will be
1562  * consumed and a g_critical() warning will be issued. The callback
1563  * will execute in the glib main loop whose GMainContext object is
1564  * passed to the 'context' argument of this method.
1565  * @param when_releaser A pointer to a Releaser object for automatic
1566  * disconnection of the 'when' callback before it executes in a main
1567  * loop (mainly relevant if the callback represents a non-static
1568  * member function of an object which may be destroyed before the
1569  * callback executes). A value of 0/NULL/nullptr indicates no
1570  * releaser.
1571  * @param fail A callback which will be executed if the 'when'
1572  * callback does not execute. This would happen if the function
1573  * passed to this method exits by throwing Thread::Exit or some other
1574  * exception, if the copy constructor of a non-reference argument of
1575  * that function throws, if the move constructor (or if it has none,
1576  * the copy constructor) of that function's return value throws or if
1577  * the 'when' callback does not execute because the internal
1578  * implementation of this wrapper throws std::bad_alloc (which will
1579  * not happen if the library has been installed using the
1580  * \--with-glib-memory-slices-no-compat configuration option: instead
1581  * glib will terminate the program if it is unable to obtain memory
1582  * from the operating system). If an exception propagates from the
1583  * 'fail' callback, this will be consumed and a g_critical() warning
1584  * will be issued. The callback will execute in the glib main loop
1585  * whose GMainContext object is passed to the 'context' argument of
1586  * this method. An empty std::unique_ptr object indicates no 'fail'
1587  * callback.
1588  * @param fail_releaser A pointer to a Releaser object for automatic
1589  * disconnection of the 'fail' callback before it executes in a main
1590  * loop (mainly relevant if the callback represents a non-static
1591  * member function of an object which may be destroyed before the
1592  * callback executes). A value of 0/NULL/nullptr indicates no
1593  * releaser.
1594  * @param priority The priority to be given in the main loop to the
1595  * 'when' callback or any 'fail' callback. In ascending order of
1596  * priorities, priorities are G_PRIORITY_LOW,
1597  * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1598  * and G_PRIORITY_HIGH. This determines the order in which the
1599  * callback will appear in the event list in the main loop, not the
1600  * priority which the OS will adopt.
1601  * @param context The glib main context of the main loop in which the
1602  * 'when' callback or any 'fail' callback is to be executed. A value
1603  * 0/NULL/nullptr will cause the callback to be executed in the main
1604  * program loop.
1605  * @param t The object whose member function passed to this method is
1606  * to execute as a task.
1607  * @param func The member function to be executed as a task. If an
1608  * exception propagates from the task, the exception will be consumed
1609  * and the 'fail' callback will execute.
1610  * @param args The arguments to be passed to that member function.
1611  * @exception std::bad_alloc This exception will be thrown if memory
1612  * is exhausted and the system throws in that case. (On systems with
1613  * over-commit/lazy-commit combined with virtual memory (swap), it is
1614  * rarely useful to check for memory exhaustion). See also the
1615  * documentation for the get_max_tasks() method about the possibility
1616  * of std::length_error being thrown. If std::bad_alloc or
1617  * std::length_error is thrown, the task will not start (which also
1618  * means that the 'when' and 'fail' callbacks will not execute).
1619  * @exception Cgu::Thread::TaskError This exception will be thrown if
1620  * stop_all() has previously been called. It will also be thrown if
1621  * is_error() would return true because this class's internal thread
1622  * pool loop implementation has thrown std::bad_alloc, or a thread
1623  * has failed to start correctly. (On systems with
1624  * over-commit/lazy-commit combined with virtual memory (swap), it is
1625  * rarely useful to check for memory exhaustion, but there may be
1626  * some specialized cases where the return value of is_error() is
1627  * useful.) If this exception is thrown, the task will not start
1628  * (which also means that the 'when' and 'fail' callbacks will not
1629  * execute).
1630  * @note 1. This method will also throw if the copy or move
1631  * constructor of a bound argument throws. If such an exception is
1632  * thrown, the task will not start (which also means that the 'when'
1633  * and 'fail' callbacks will not execute).
1634  * @note 2. If a 'when_releaser' or a 'fail_releaser' object is
1635  * provided, it is in theory possible (if memory is exhausted and the
1636  * system throws in that case) that an internal SafeEmitterArg object
1637  * will throw std::bad_alloc when emitting/executing the 'when' or
1638  * 'fail' callback in the glib main loop, with the result that the
1639  * relevant callback will not execute (instead the exception will be
1640  * consumed and a g_critical() warning will be issued). This is
1641  * rarely of any relevance because glib will abort the program if it
1642  * is itself unable to obtain memory from the operating system.
1643  * However, where it is relevant, design the program so that it is
1644  * not necessary to provide a releaser object.
1645  *
1646  * Since 2.0.13
1647  */
1648  template <class Ret, class... Params, class... Args, class T>
1649  void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1650  Cgu::Releaser* when_releaser,
1651  std::unique_ptr<const Cgu::Callback::Callback> fail,
1652  Cgu::Releaser* fail_releaser,
1653  gint priority,
1654  GMainContext* context,
1655  const T& t,
1656  Ret (T::*func)(Params...) const,
1657  Args&&... args);
1658 
1659  /**
1660  * @deprecated
1661  *
1662  * DEPRECATED. Use the versions of make_task_when() which take
1663  * callable objects.
1664  *
1665  * This is an abbreviated version of make_task_when_full(), which is
1666  * for use when it is known that invocation of the member function
1667  * passed to this method, the copy constructors of any non-reference
1668  * arguments of that function and the move constructor (or if it has
1669  * none, the copy constructor) of that function's return value do not
1670  * throw anything other than std::bad_alloc, and the user is not
1671  * interested in std::bad_alloc and does not need a Cgu::Releaser
1672  * object for the 'when' callback (which is likely to cover the
1673  * majority of uses, particularly when composing tasks using glib
1674  * because glib terminates the program if it is unable to obtain
1675  * memory).
1676  *
1677  * This method can take up to three bound arguments for the target
1678  * member function.
1679  *
1680  * Like make_task_when_full(), this method is a wrapper which takes a
1681  * member function pointer to a member function which returns a
1682  * value, together with arguments, and constructs a TaskManager task
1683  * which will execute that function by calling add_task() with an
1684  * appropriate callback object, and causes the 'when' callback passed
1685  * as an argument to this method to be executed by a glib main loop
1686  * if and when the task finishes correctly - the 'when' callback is
1687  * passed the member function's return value when it is invoked. It
1688  * is thread safe (any thread may call this method, including another
1689  * task running on the TaskManager object). Apart from the absence
1690  * of a 'one thread per task' model, this method therefore provides a
1691  * similar interface to the one provided by Cgu::Thread::Future. See
1692  * the documentation on add_task() for further information about how
1693  * task execution works.
1694  *
1695  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
1696  * in the main loop.
1697  *
1698  * @param when A callback which will be executed if and when the
1699  * function passed to this method finishes correctly. The callback is
1700  * passed that function's return value when it is invoked. If an
1701  * exception propagates from the 'when' callback, this will be
1702  * consumed and a g_critical() warning will be issued. The callback
1703  * will execute in the glib main loop whose GMainContext object is
1704  * passed to the 'context' argument of this method.
1705  * @param context The glib main context of the main loop in which the
1706  * 'when' callback is to be executed. A value 0/NULL/nullptr will
1707  * cause the callback to be executed in the main program loop.
1708  * @param t The object whose member function passed to this method is
1709  * to execute as a task.
1710  * @param func The member function to be executed as a task. If an
1711  * exception propagates from the task, the exception will be consumed
1712  * and (if the thrown object's type is not Cgu::Thread::Exit) a
1713  * g_critical() warning will be issued.
1714  * @param args The arguments to be passed to that member function.
1715  * @exception std::bad_alloc This exception will be thrown if memory
1716  * is exhausted and the system throws in that case. (On systems with
1717  * over-commit/lazy-commit combined with virtual memory (swap), it is
1718  * rarely useful to check for memory exhaustion). See also the
1719  * documentation for the get_max_tasks() method about the possibility
1720  * of std::length_error being thrown. If std::bad_alloc or
1721  * std::length_error is thrown, the task will not start (which also
1722  * means that the 'when' callback will not execute).
1723  * @exception Cgu::Thread::TaskError This exception will be thrown if
1724  * stop_all() has previously been called. It will also be thrown if
1725  * is_error() would return true because this class's internal thread
1726  * pool loop implementation has thrown std::bad_alloc, or a thread
1727  * has failed to start correctly. (On systems with
1728  * over-commit/lazy-commit combined with virtual memory (swap), it is
1729  * rarely useful to check for memory exhaustion, but there may be
1730  * some specialized cases where the return value of is_error() is
1731  * useful.) If this exception is thrown, the task will not start
1732  * (which also means that the 'when' callback will not execute).
1733  * @note 1. This method will also throw if the copy or move
1734  * constructor of a bound argument throws. If such an exception is
1735  * thrown, the task will not start (which also means that the 'when'
1736  * callback will not execute).
1737  * @note 2. As mentioned in describing 'func' above, if 'func' exits
1738  * by throwing an exception the exception will be consumed and (if
1739  * the thrown object's type is not Cgu::Thread::Exit) a g_critical()
1740  * warning will be issued. The same will occur if the copy
1741  * constructor of a non-reference argument of 'func' throws when
1742  * invoking 'func' or the move constructor (or if it has none, the
1743  * copy constructor) of the return value of 'func' throws, or if the
1744  * internal implementation of this wrapper throws std::bad_alloc on
1745  * executing 'func'.
1746  *
1747  * Since 2.0.13
1748  */
1749  template <class Ret, class... Params, class... Args, class T>
1750  void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1751  GMainContext* context,
1752  const T& t,
1753  Ret (T::*func)(Params...) const,
1754  Args&&... args) {
1755  static_assert(sizeof...(Args) < 4,
1756  "No greater than three bound arguments can be passed to "
1757  "TaskManager::make_task_when() taking a member function.");
1758 
1759  make_task_when_full(std::move(when),
1760  0,
1761  std::unique_ptr<const Cgu::Callback::Callback>(),
1762  0,
1763  G_PRIORITY_DEFAULT,
1764  context,
1765  t,
1766  func,
1767  std::forward<Args>(args)...);
1768  }
1769 
1770  /**
1771  * @deprecated
1772  *
1773  * DEPRECATED. Use the versions of make_task_result() which take
1774  * callable objects.
1775  *
1776  * This is a wrapper which takes a pointer to a function which
1777  * returns a value, together with arguments, and constructs a
1778  * TaskManager task which will execute that function by calling
1779  * add_task() with an appropriate callback object, and returns a
1780  * Cgu::AsyncResult object (held by Cgu::SharedLockPtr) which will
1781  * provide the value that the function returns. Apart from the
1782  * absence of a 'one thread per task' model, this method therefore
1783  * provides a similar interface to the one provided by
1784  * Cgu::Thread::Future. It is thread safe: any thread may call this
1785  * method, including another task running on the TaskManager object,
1786  * but see the introductory remarks about the use of the
1787  * TaskManager::IncHandle scoped handle class where a task running on
1788  * a TaskManager object is to block on one of its sub-tasks. See
1789  * also the documentation on add_task() for further information about
1790  * how task execution works.
1791  *
1792  * This method can take up to four bound arguments for the target
1793  * function.
1794  *
1795  * If the function passed to this method exits by throwing
1796  * Thread::Exit or some other exception, then the exception will be
1797  * consumed and the returned Cgu::AsyncResult object's get() or
1798  * move_get() method will unblock and its get_error() method will
1799  * return -1.
1800  *
1801  * @param func The function to be executed as a task.
1802  * @param args The arguments to be passed to that function.
1803  * @exception std::bad_alloc This exception will be thrown if memory
1804  * is exhausted and the system throws in that case. (On systems with
1805  * over-commit/lazy-commit combined with virtual memory (swap), it is
1806  * rarely useful to check for memory exhaustion). See also the
1807  * documentation for the get_max_tasks() method about the possibility
1808  * of std::length_error being thrown. If std::bad_alloc or
1809  * std::length_error is thrown, the task will not start.
1810  * @exception Cgu::Thread::TaskError This exception will be thrown if
1811  * stop_all() has previously been called. It will also be thrown if
1812  * is_error() would return true because this class's internal thread
1813  * pool loop implementation has thrown std::bad_alloc, or a thread
1814  * has failed to start correctly. (On systems with
1815  * over-commit/lazy-commit combined with virtual memory (swap), it is
1816  * rarely useful to check for memory exhaustion, but there may be
1817  * some specialized cases where the return value of is_error() is
1818  * useful.) If this exception is thrown, the task will not start.
1819  * @note This method will also throw if the copy or move constructor
1820  * of a bound argument throws. If such an exception is thrown, the
1821  * task will not start.
1822  *
1823  * Since 2.0.13
1824  */
1825  template <class Ret, class... Params, class... Args>
1827  Args&&... args);
1828 
1829  /**
1830  * @deprecated
1831  *
1832  * DEPRECATED. Use the versions of make_task_when_full() which take
1833  * callable objects.
1834  *
1835  * This is a wrapper which takes a pointer to a function which
1836  * returns a value, together with arguments, and constructs a
1837  * TaskManager task which will execute that function by calling
1838  * add_task() with an appropriate callback object, and causes the
1839  * 'when' callback passed as an argument to this method to be
1840  * executed by a glib main loop if and when the task finishes
1841  * correctly - the 'when' callback is passed the function's return
1842  * value when it is invoked. It is thread safe (any thread may call
1843  * this method, including another task running on the TaskManager
1844  * object). Apart from the absence of a 'one thread per task' model,
1845  * this method therefore provides a similar interface to the one
1846  * provided by Cgu::Thread::Future. See the documentation on
1847  * add_task() for further information about how task execution works.
1848  *
1849  * This method can take up to four bound arguments for the target
1850  * function.
1851  *
1852  * Note that unlike add_task(), but like the 'fail' callback of
1853  * Cgu::Thread::Future objects, if a fail callback is provided to
1854  * this method and it executes, it will execute in the glib main loop
1855  * whose GMainContext object is passed to the 'context' argument of
1856  * this method.
1857  *
1858  * Note also that if releasers are provided for the 'when' or 'fail'
1859  * callbacks, these are passed by pointer and not by reference (this
1860  * is so that a NULL pointer can indicate that no releaser is to be
1861  * provided). If provided, a releaser will enable automatic
1862  * disconnection of the 'when' or 'fail' callback, if the object of
1863  * which the releaser is a member is destroyed. For this to be race
1864  * free, the lifetime of that object must be controlled by the thread
1865  * in whose main loop the 'when' or 'fail' callback will execute.
1866  *
1867  * The make_task_when() method is similar to this method but provides
1868  * an abbreviated set of paramaters suitable for most cases. This
1869  * method is for use where releasers or a 'fail' callback are
1870  * required.
1871  *
1872  * @param when A callback which will be executed if and when the
1873  * function passed to this method finishes correctly. The callback is
1874  * passed that function's return value when it is invoked. If an
1875  * exception propagates from the 'when' callback, this will be
1876  * consumed and a g_critical() warning will be issued. The callback
1877  * will execute in the glib main loop whose GMainContext object is
1878  * passed to the 'context' argument of this method.
1879  * @param when_releaser A pointer to a Releaser object for automatic
1880  * disconnection of the 'when' callback before it executes in a main
1881  * loop (mainly relevant if the callback represents a non-static
1882  * member function of an object which may be destroyed before the
1883  * callback executes). A value of 0/NULL/nullptr indicates no
1884  * releaser.
1885  * @param fail A callback which will be executed if the 'when'
1886  * callback does not execute. This would happen if the function
1887  * passed to this method exits by throwing Thread::Exit or some other
1888  * exception, if the copy constructor of a non-reference argument of
1889  * that function throws, if the move constructor (or if it has none,
1890  * the copy constructor) of that function's return value throws or if
1891  * the 'when' callback does not execute because the internal
1892  * implementation of this wrapper throws std::bad_alloc (which will
1893  * not happen if the library has been installed using the
1894  * \--with-glib-memory-slices-no-compat configuration option: instead
1895  * glib will terminate the program if it is unable to obtain memory
1896  * from the operating system). If an exception propagates from the
1897  * 'fail' callback, this will be consumed and a g_critical() warning
1898  * will be issued. The callback will execute in the glib main loop
1899  * whose GMainContext object is passed to the 'context' argument of
1900  * this method. An empty std::unique_ptr object indicates no 'fail'
1901  * callback.
1902  * @param fail_releaser A pointer to a Releaser object for automatic
1903  * disconnection of the 'fail' callback before it executes in a main
1904  * loop (mainly relevant if the callback represents a non-static
1905  * member function of an object which may be destroyed before the
1906  * callback executes). A value of 0/NULL/nullptr indicates no
1907  * releaser.
1908  * @param priority The priority to be given in the main loop to the
1909  * 'when' callback or any 'fail' callback. In ascending order of
1910  * priorities, priorities are G_PRIORITY_LOW,
1911  * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
1912  * and G_PRIORITY_HIGH. This determines the order in which the
1913  * callback will appear in the event list in the main loop, not the
1914  * priority which the OS will adopt.
1915  * @param context The glib main context of the main loop in which the
1916  * 'when' callback or any 'fail' callback is to be executed. A value
1917  * 0/NULL/nullptr will cause the callback to be executed in the main
1918  * program loop.
1919  * @param func The function to be executed as a task. If an
1920  * exception propagates from the task, the exception will be consumed
1921  * and the 'fail' callback will execute.
1922  * @param args The arguments to be passed to that function.
1923  * @exception std::bad_alloc This exception will be thrown if memory
1924  * is exhausted and the system throws in that case. (On systems with
1925  * over-commit/lazy-commit combined with virtual memory (swap), it is
1926  * rarely useful to check for memory exhaustion). See also the
1927  * documentation for the get_max_tasks() method about the possibility
1928  * of std::length_error being thrown. If std::bad_alloc or
1929  * std::length_error is thrown, the task will not start (which also
1930  * means that the 'when' and 'fail' callbacks will not execute).
1931  * @exception Cgu::Thread::TaskError This exception will be thrown if
1932  * stop_all() has previously been called. It will also be thrown if
1933  * is_error() would return true because this class's internal thread
1934  * pool loop implementation has thrown std::bad_alloc, or a thread
1935  * has failed to start correctly. (On systems with
1936  * over-commit/lazy-commit combined with virtual memory (swap), it is
1937  * rarely useful to check for memory exhaustion, but there may be
1938  * some specialized cases where the return value of is_error() is
1939  * useful.) If this exception is thrown, the task will not start
1940  * (which also means that the 'when' and 'fail' callbacks will not
1941  * execute).
1942  * @note 1. This method will also throw if the copy or move
1943  * constructor of a bound argument throws. If such an exception is
1944  * thrown, the task will not start (which also means that the 'when'
1945  * and 'fail' callbacks will not execute).
1946  * @note 2. If a 'when_releaser' or a 'fail_releaser' object is
1947  * provided, it is in theory possible (if memory is exhausted and the
1948  * system throws in that case) that an internal SafeEmitterArg object
1949  * will throw std::bad_alloc when emitting/executing the 'when' or
1950  * 'fail' callback in the glib main loop, with the result that the
1951  * relevant callback will not execute (instead the exception will be
1952  * consumed and a g_critical() warning will be issued). This is
1953  * rarely of any relevance because glib will abort the program if it
1954  * is itself unable to obtain memory from the operating system.
1955  * However, where it is relevant, design the program so that it is
1956  * not necessary to provide a releaser object.
1957  *
1958  * Since 2.0.13
1959  */
1960  template <class Ret, class... Params, class... Args>
1961  void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
1962  Cgu::Releaser* when_releaser,
1963  std::unique_ptr<const Cgu::Callback::Callback> fail,
1964  Cgu::Releaser* fail_releaser,
1965  gint priority,
1966  GMainContext* context,
1967  Ret (*func)(Params...),
1968  Args&&... args);
1969 
1970  /**
1971  * @deprecated
1972  *
1973  * DEPRECATED. Use the versions of make_task_when() which take
1974  * callable objects.
1975  *
1976  * This is an abbreviated version of make_task_when_full(), which is
1977  * for use when it is known that invocation of the function passed to
1978  * this method, the copy constructors of any non-reference arguments
1979  * of that function and the move constructor (or if it has none, the
1980  * copy constructor) of that function's return value do not throw
1981  * anything other than std::bad_alloc, and the user is not interested
1982  * in std::bad_alloc and does not need a Cgu::Releaser object for the
1983  * 'when' callback (which is likely to cover the majority of uses,
1984  * particularly when composing tasks using glib because glib
1985  * terminates the program if it is unable to obtain memory).
1986  *
1987  * This method can take up to four bound arguments for the target
1988  * function.
1989  *
1990  * Like make_task_when_full(), this method is a wrapper which takes a
1991  * pointer to a function which returns a value, together with
1992  * arguments, and constructs a TaskManager task which will execute
1993  * that function by calling add_task() with an appropriate callback
1994  * object, and causes the 'when' callback passed as an argument to
1995  * this method to be executed by a glib main loop if and when the
1996  * task finishes correctly - the 'when' callback is passed the
1997  * function's return value when it is invoked. It is thread safe
1998  * (any thread may call this method, including another task running
1999  * on the TaskManager object). Apart from the absence of a 'one
2000  * thread per task' model, this method therefore provides a similar
2001  * interface to the one provided by Cgu::Thread::Future. See the
2002  * documentation on add_task() for further information about how task
2003  * execution works.
2004  *
2005  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2006  * in the main loop.
2007  *
2008  * @param when A callback which will be executed if and when the
2009  * function passed to this method finishes correctly. The callback is
2010  * passed that function's return value when it is invoked. If an
2011  * exception propagates from the 'when' callback, this will be
2012  * consumed and a g_critical() warning will be issued. The callback
2013  * will execute in the glib main loop whose GMainContext object is
2014  * passed to the 'context' argument of this method.
2015  * @param context The glib main context of the main loop in which the
2016  * 'when' callback is to be executed. A value 0/NULL/nullptr will
2017  * cause the callback to be executed in the main program loop.
2018  * @param func The function to be executed as a task. If an
2019  * exception propagates from the task, the exception will be consumed
2020  * and (if the thrown object's type is not Cgu::Thread::Exit) a
2021  * g_critical() warning will be issued.
2022  * @param args The arguments to be passed to that function.
2023  * @exception std::bad_alloc This exception will be thrown if memory
2024  * is exhausted and the system throws in that case. (On systems with
2025  * over-commit/lazy-commit combined with virtual memory (swap), it is
2026  * rarely useful to check for memory exhaustion). See also the
2027  * documentation for the get_max_tasks() method about the possibility
2028  * of std::length_error being thrown. If std::bad_alloc or
2029  * std::length_error is thrown, the task will not start (which also
2030  * means that the 'when' callback will not execute).
2031  * @exception Cgu::Thread::TaskError This exception will be thrown if
2032  * stop_all() has previously been called. It will also be thrown if
2033  * is_error() would return true because this class's internal thread
2034  * pool loop implementation has thrown std::bad_alloc, or a thread
2035  * has failed to start correctly. (On systems with
2036  * over-commit/lazy-commit combined with virtual memory (swap), it is
2037  * rarely useful to check for memory exhaustion, but there may be
2038  * some specialized cases where the return value of is_error() is
2039  * useful.) If this exception is thrown, the task will not start
2040  * (which also means that the 'when' callback will not execute).
2041  * @note 1. This method will also throw if the copy or move
2042  * constructor of a bound argument throws. If such an exception is
2043  * thrown, the task will not start (which also means that the 'when'
2044  * callback will not execute).
2045  * @note 2. As mentioned in describing 'func' above, if 'func' exits
2046  * by throwing an exception the exception will be consumed and (if
2047  * the thrown object's type is not Cgu::Thread::Exit) a g_critical()
2048  * warning will be issued. The same will occur if the copy
2049  * constructor of a non-reference argument of 'func' throws when
2050  * invoking 'func' or the move constructor (or if it has none, the
2051  * copy constructor) of the return value of 'func' throws, or if the
2052  * internal implementation of this wrapper throws std::bad_alloc on
2053  * executing 'func'.
2054  *
2055  * Since 2.0.13
2056  */
2057  template <class Ret, class... Params, class... Args>
2058  void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
2059  GMainContext* context,
2060  Ret (*func)(Params...),
2061  Args&&... args) {
2062  static_assert(sizeof...(Args) < 5,
2063  "No greater than four bound arguments can be passed to "
2064  "TaskManager::make_task_when() taking a function.");
2065 
2066  make_task_when_full(std::move(when),
2067  0,
2068  std::unique_ptr<const Cgu::Callback::Callback>(),
2069  0,
2070  G_PRIORITY_DEFAULT,
2071  context,
2072  func,
2073  std::forward<Args>(args)...);
2074  }
2075 
2076  /**
2077  * This is a wrapper which takes a callable object which returns a
2078  * value (such as a std::function object, a lambda or the return
2079  * value of std::bind), and constructs a TaskManager task which will
2080  * execute that object by calling add_task() with an appropriate
2081  * callback object, and returns a Cgu::AsyncResult object (held by
2082  * Cgu::SharedLockPtr) which will provide the value that it returns.
2083  * Apart from the absence of a 'one thread per task' model, this
2084  * method therefore provides a similar interface to the one provided
2085  * by Cgu::Thread::Future. It is thread safe: any thread may call
2086  * this method, including another task running on the TaskManager
2087  * object, but see the introductory remarks about the use of the
2088  * TaskManager::IncHandle scoped handle class where a task running on
2089  * a TaskManager object is to block on one of its sub-tasks. See
2090  * also the documentation on add_task() for further information about
2091  * how task execution works.
2092  *
2093  * If the callable object passed to this method exits by throwing
2094  * Thread::Exit or some other exception, then the exception will be
2095  * consumed and the returned Cgu::AsyncResult object's get() or
2096  * move_get() method will unblock and its get_error() method will
2097  * return -1.
2098  *
2099  * @param f The callable object to be executed as a task, such as
2100  * formed by a lambda expression or the result of std::bind. It
2101  * should return a value (it cannot return void).
2102  * @exception std::bad_alloc This exception will be thrown if memory
2103  * is exhausted and the system throws in that case. (On systems with
2104  * over-commit/lazy-commit combined with virtual memory (swap), it is
2105  * rarely useful to check for memory exhaustion). See also the
2106  * documentation for the get_max_tasks() method about the possibility
2107  * of std::length_error being thrown. If std::bad_alloc or
2108  * std::length_error is thrown, the task will not start.
2109  * @exception Cgu::Thread::TaskError This exception will be thrown if
2110  * stop_all() has previously been called. It will also be thrown if
2111  * is_error() would return true because this class's internal thread
2112  * pool loop implementation has thrown std::bad_alloc, or a thread
2113  * has failed to start correctly. (On systems with
2114  * over-commit/lazy-commit combined with virtual memory (swap), it is
2115  * rarely useful to check for memory exhaustion, but there may be
2116  * some specialized cases where the return value of is_error() is
2117  * useful.) If this exception is thrown, the task will not start.
2118  * @note 1. This method will also throw if the copy or move
2119  * constructor of the callable object throws. If such an exception
2120  * is thrown, the task will not start.
2121  * @note 2. If the callable object passed as an argument has both
2122  * const and non-const operator()() methods, the non-const version
2123  * will be called even if the callable object passed is a const
2124  * object.
2125  *
2126  * Since 2.0.14
2127  */
2128  // we don't need this version of make_task_result() for syntactic
2129  // reasons - the version taking a single template parameter will do
2130  // by itself syntactically because it can use decltype. However, we
2131  // include this version in order to be API compatible with
2132  // c++-gtk-utils < 2.0.14, which required the return type to be
2133  // specified when this method is passed something other than a
2134  // std::function object. SFINAE will take care of the rest, except
2135  // with a corner case where all of the following apply: (i) a
2136  // function object is passed whose operator()() method returns a
2137  // copy of the function object (or another function object of the
2138  // same type), (ii) the function object is passed to this method as
2139  // a rvalue and not a lvalue, and (iii) the user specifically states
2140  // the return type when instantiating this template function. This
2141  // would give rise to an ambiguity, but its happening is extremely
2142  // unlikely, and cannot happen with a lambda or the return value of
2143  // std::bind, because those types are only known to the compiler,
2144  // and cannot happen with other objects if the user lets template
2145  // deduction take its course.
2146  template <class Ret, class Func>
2148 
2149  // we don't want to document this function: it provides the type
2150  // deduction of the return value of the passed functor (it deals
2151  // with cases where this is not specified expressly).
2152 #ifndef DOXYGEN_PARSING
2153  template <class Func>
2155 
2156  // TODO: this is a work-around for gcc < 4.7, which has a bug
2157  // which requires a function whose return value is determined by
2158  // decltype, such as make_task_result(Func&&), to be inline. At a
2159  // suitable API/ABI break when gcc requirements are updated, this
2160  // should be moved to task_manager.tpp.
2161 
2162  // there are two types related to the functor to be executed by
2163  // the task. 'Func' is the transient type provided by argument
2164  // deduction for forwarding, and will vary depending on whether
2165  // the functor object is a lvalue (which will deduce it as a
2166  // reference type) or rvalue (which will not). 'FType' is the
2167  // type to be held by the callback object generated in this
2168  // function, and is never a reference type. It is also never
2169  // const, because the FType member is marked mutable in the
2170  // callback object so that it can execute mutable lambdas (or
2171  // other functors with a non-const operator()() method).
2172  typedef typename std::remove_const<typename std::remove_reference<Func>::type>::type FType;
2173  // this method will fail to compile if Ret is a reference type:
2174  // that is a feature, not a bug, as a function returning a
2175  // reference lacks referential transparency, is unlikely to be
2176  // thread-safe and is unsuitable for use as a task function
2177  typedef decltype(f()) Ret;
2178  typedef std::unique_ptr<const Callback::Callback> CbPtr;
2179 
2181  CbPtr exec_cb(new TaskManagerHelper2::FunctorResultExec<Ret, FType>(std::forward<Func>(f), ret));
2182  CbPtr do_fail_cb(Callback::make_ref(&TaskManagerHelper2::FunctorResultWrapper<Ret, FType>::do_fail,
2183  ret));
2184  add_task(std::move(exec_cb), std::move(do_fail_cb));
2185 
2186  return ret;
2187  }
2188 #endif
2189 
2190  /**
2191  * This is a wrapper which takes a callable object which returns a
2192  * value (such as a std::function object, a lambda or the return
2193  * value of std::bind), and constructs a TaskManager task which will
2194  * execute that object by calling add_task() with an appropriate
2195  * callback object, and causes the 'when' callback passed as an
2196  * argument to this method to be executed by a glib main loop if and
2197  * when the task finishes correctly - the 'when' callback is passed
2198  * the callable object's return value when it is invoked. It is
2199  * thread safe (any thread may call this method, including another
2200  * task running on the TaskManager object). Apart from the absence
2201  * of a 'one thread per task' model, this method therefore provides a
2202  * similar interface to the one provided by Cgu::Thread::Future. See
2203  * the documentation on add_task() for further information about how
2204  * task execution works.
2205  *
2206  * Note that unlike add_task(), but like the 'fail' callback of
2207  * Cgu::Thread::Future objects, if a fail callback is provided to
2208  * this method and it executes, it will execute in the glib main loop
2209  * whose GMainContext object is passed to the 'context' argument of
2210  * this method.
2211  *
2212  * Note also that if releasers are provided for the 'when' or 'fail'
2213  * callbacks, these are passed by pointer and not by reference (this
2214  * is so that a NULL pointer can indicate that no releaser is to be
2215  * provided). If provided, a releaser will enable automatic
2216  * disconnection of the 'when' or 'fail' callback, if the object of
2217  * which the releaser is a member is destroyed. For this to be race
2218  * free, the lifetime of that object must be controlled by the thread
2219  * in whose main loop the 'when' or 'fail' callback will execute.
2220  *
2221  * The make_task_when() method is similar to this method but provides
2222  * an abbreviated set of parameters suitable for most cases. This
2223  * method is for use where releasers or a 'fail' callback are
2224  * required.
2225  *
2226  * @param when A callback which will be executed if and when the
2227  * callable object passed as 'func' to this method finishes
2228  * correctly. The callback is passed that object's return value when
2229  * it is invoked. If an exception propagates from the 'when'
2230  * callback, this will be consumed and a g_critical() warning will be
2231  * issued. The callback will execute in the glib main loop whose
2232  * GMainContext object is passed to the 'context' argument of this
2233  * method.
2234  * @param when_releaser A pointer to a Releaser object for automatic
2235  * disconnection of the 'when' callback before it executes in a main
2236  * loop (mainly relevant if the callback represents a non-static
2237  * member function of an object which may be destroyed before the
2238  * callback executes). A value of 0/NULL/nullptr indicates no
2239  * releaser.
2240  * @param fail A callback which will be executed if the 'when'
2241  * callback does not execute. This would happen if the callable
2242  * object passed as 'func' to this method exits by throwing
2243  * Thread::Exit or some other exception, if the move constructor (or
2244  * if it has none, the copy constructor) of that object's return
2245  * value throws or if the 'when' callback does not execute because
2246  * the internal implementation of this wrapper throws std::bad_alloc
2247  * (which will not happen if the library has been installed using the
2248  * \--with-glib-memory-slices-no-compat configuration option: instead
2249  * glib will terminate the program if it is unable to obtain memory
2250  * from the operating system). If an exception propagates from the
2251  * 'fail' callback, this will be consumed and a g_critical() warning
2252  * will be issued. The callback will execute in the glib main loop
2253  * whose GMainContext object is passed to the 'context' argument of
2254  * this method. An empty std::unique_ptr object indicates no 'fail'
2255  * callback.
2256  * @param fail_releaser A pointer to a Releaser object for automatic
2257  * disconnection of the 'fail' callback before it executes in a main
2258  * loop (mainly relevant if the callback represents a non-static
2259  * member function of an object which may be destroyed before the
2260  * callback executes). A value of 0/NULL/nullptr indicates no
2261  * releaser.
2262  * @param priority The priority to be given in the main loop to the
2263  * 'when' callback or any 'fail' callback. In ascending order of
2264  * priorities, priorities are G_PRIORITY_LOW,
2265  * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
2266  * and G_PRIORITY_HIGH. This determines the order in which the
2267  * callback will appear in the event list in the main loop, not the
2268  * priority which the OS will adopt.
2269  * @param context The glib main context of the main loop in which the
2270  * 'when' callback or any 'fail' callback is to be executed. A value
2271  * 0/NULL/nullptr will cause the callback to be executed in the main
2272  * program loop.
2273  * @param func The callable object to be executed as a task, such as
2274  * formed by a lambda expression or the result of std::bind. It
2275  * should return a value (it cannot return void). It must be fully
2276  * bound (that is, it must take no arguments when called). If an
2277  * exception propagates from the task, the exception will be consumed
2278  * and the 'fail' callback will execute.
2279  * @exception std::bad_alloc This exception will be thrown if memory
2280  * is exhausted and the system throws in that case. (On systems with
2281  * over-commit/lazy-commit combined with virtual memory (swap), it is
2282  * rarely useful to check for memory exhaustion). See also the
2283  * documentation for the get_max_tasks() method about the possibility
2284  * of std::length_error being thrown. If std::bad_alloc or
2285  * std::length_error is thrown, the task will not start (which also
2286  * means that the 'when' and 'fail' callbacks will not execute).
2287  * @exception Cgu::Thread::TaskError This exception will be thrown if
2288  * stop_all() has previously been called. It will also be thrown if
2289  * is_error() would return true because this class's internal thread
2290  * pool loop implementation has thrown std::bad_alloc, or a thread
2291  * has failed to start correctly. (On systems with
2292  * over-commit/lazy-commit combined with virtual memory (swap), it is
2293  * rarely useful to check for memory exhaustion, but there may be
2294  * some specialized cases where the return value of is_error() is
2295  * useful.) If this exception is thrown, the task will not start
2296  * (which also means that the 'when' and 'fail' callbacks will not
2297  * execute).
2298  * @note 1. This method will also throw if the copy or move
2299  * constructor of the callable object throws. If such an exception
2300  * is thrown, the task will not start (which also means that the
2301  * 'when' and 'fail' callbacks will not execute).
2302  * @note 2. If the callable object passed as an argument has both
2303  * const and non-const operator()() methods, the non-const version
2304  * will be called even if the callable object passed is a const
2305  * object.
2306  * @note 3. If a 'when_releaser' or a 'fail_releaser' object is
2307  * provided, it is in theory possible (if memory is exhausted and the
2308  * system throws in that case) that an internal SafeEmitterArg object
2309  * will throw std::bad_alloc when emitting/executing the 'when' or
2310  * 'fail' callback in the glib main loop, with the result that the
2311  * relevant callback will not execute (instead the exception will be
2312  * consumed and a g_critical() warning will be issued). This is
2313  * rarely of any relevance because glib will abort the program if it
2314  * is itself unable to obtain memory from the operating system.
2315  * However, where it is relevant, design the program so that it is
2316  * not necessary to provide a releaser object.
2317  *
2318  * Since 2.0.14
2319  */
2320  template <class Ret, class Func>
2321  void make_task_when_full(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
2322  Cgu::Releaser* when_releaser,
2323  std::unique_ptr<const Cgu::Callback::Callback> fail,
2324  Cgu::Releaser* fail_releaser,
2325  gint priority,
2326  GMainContext* context,
2327  Func&& func);
2328 
2329  /**
2330  * This is a wrapper which takes a callable object which returns a
2331  * value as its 'func' argument (such as a std::function object, a
2332  * lambda or the return value of std::bind), and constructs a
2333  * TaskManager task which will execute that object by calling
2334  * add_task() with an appropriate callback object, and causes the
2335  * 'when' callback passed as an argument to this method to be
2336  * executed by a glib main loop if and when the task finishes
2337  * correctly - the 'when' callback is passed the return value of the
2338  * 'func' argument when it is invoked. It is thread safe (any thread
2339  * may call this method, including another task running on the
2340  * TaskManager object). Apart from the absence of a 'one thread per
2341  * task' model, this method therefore provides a similar interface to
2342  * the one provided by Cgu::Thread::Future. See the documentation on
2343  * add_task() for further information about how task execution works.
2344  *
2345  * Note that unlike add_task(), but like the 'fail' callback of
2346  * Cgu::Thread::Future objects, if a fail callback is provided to
2347  * this method and it executes, it will execute in the glib main loop
2348  * whose GMainContext object is passed to the 'context' argument of
2349  * this method.
2350  *
2351  * Note also that if releasers are provided for the 'when' or 'fail'
2352  * callbacks, these are passed by pointer and not by reference (this
2353  * is so that a NULL pointer can indicate that no releaser is to be
2354  * provided). If provided, a releaser will enable automatic
2355  * disconnection of the 'when' or 'fail' callback, if the object of
2356  * which the releaser is a member is destroyed. For this to be race
2357  * free, the lifetime of that object must be controlled by the thread
2358  * in whose main loop the 'when' or 'fail' callback will execute.
2359  *
2360  * The make_task_when() method is similar to this method but provides
2361  * an abbreviated set of parameters suitable for most cases. This
2362  * method is for use where releasers or a 'fail' callback are
2363  * required.
2364  *
2365  * @param when A callable object (such as formed by a lambda
2366  * expression or the result of std::bind) which will be executed if
2367  * and when the 'func' object passed to this method finishes
2368  * correctly. The 'when' callback is passed that objects's return
2369  * value when invoked, and should take a single unbound argument,
2370  * namely a reference to const of the type of that return value. If
2371  * an exception propagates from the 'when' callback, this will be
2372  * consumed and a g_critical() warning will be issued. The callback
2373  * will execute in the glib main loop whose GMainContext object is
2374  * passed to the 'context' argument of this method.
2375  * @param when_releaser A pointer to a Releaser object for automatic
2376  * disconnection of the 'when' callback before it executes in a main
2377  * loop (mainly relevant if the callback calls a non-static member
2378  * function of an object which may be destroyed before the callback
2379  * executes). A value of 0/NULL/nullptr indicates no releaser.
2380  * @param fail A callable object (such as formed by a lambda
2381  * expression or the result of std::bind) which will be executed if
2382  * the 'when' callback does not execute. This would happen if the
2383  * callable object passed as 'func' to this method exits by throwing
2384  * Thread::Exit or some other exception, if the move constructor (or
2385  * if it has none, the copy constructor) of that object's return
2386  * value throws or if the 'when' callback does not execute because
2387  * the internal implementation of this wrapper throws std::bad_alloc
2388  * (which will not happen if the library has been installed using the
2389  * \--with-glib-memory-slices-no-compat configuration option: instead
2390  * glib will terminate the program if it is unable to obtain memory
2391  * from the operating system). The callable object must be fully
2392  * bound (that is, it must take no arguments when called). If an
2393  * exception propagates from the 'fail' callback, this will be
2394  * consumed and a g_critical() warning will be issued. The callback
2395  * will execute in the glib main loop whose GMainContext object is
2396  * passed to the 'context' argument of this method. If no 'fail'
2397  * callback is wanted, pass a lambda which does nothing.
2398  * @param fail_releaser A pointer to a Releaser object for automatic
2399  * disconnection of the 'fail' callback before it executes in a main
2400  * loop (mainly relevant if the callback calls a non-static member
2401  * function of an object which may be destroyed before the callback
2402  * executes). A value of 0/NULL/nullptr indicates no releaser.
2403  * @param priority The priority to be given in the main loop to the
2404  * 'when' callback or any 'fail' callback. In ascending order of
2405  * priorities, priorities are G_PRIORITY_LOW,
2406  * G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT
2407  * and G_PRIORITY_HIGH. This determines the order in which the
2408  * callback will appear in the event list in the main loop, not the
2409  * priority which the OS will adopt.
2410  * @param context The glib main context of the main loop in which the
2411  * 'when' callback or any 'fail' callback is to be executed. A value
2412  * 0/NULL/nullptr will cause the callback to be executed in the main
2413  * program loop.
2414  * @param func The callable object to be executed as a task, such as
2415  * formed by a lambda expression or the result of std::bind. It
2416  * should return a value (it cannot return void). It must be fully
2417  * bound (that is, it must take no arguments when called). If an
2418  * exception propagates from the task, the exception will be consumed
2419  * and the 'fail' callback will execute.
2420  * @exception std::bad_alloc This exception will be thrown if memory
2421  * is exhausted and the system throws in that case. (On systems with
2422  * over-commit/lazy-commit combined with virtual memory (swap), it is
2423  * rarely useful to check for memory exhaustion). See also the
2424  * documentation for the get_max_tasks() method about the possibility
2425  * of std::length_error being thrown. If std::bad_alloc or
2426  * std::length_error is thrown, the task will not start (which also
2427  * means that the 'when' and 'fail' callbacks will not execute).
2428  * @exception Cgu::Thread::TaskError This exception will be thrown if
2429  * stop_all() has previously been called. It will also be thrown if
2430  * is_error() would return true because this class's internal thread
2431  * pool loop implementation has thrown std::bad_alloc, or a thread
2432  * has failed to start correctly. (On systems with
2433  * over-commit/lazy-commit combined with virtual memory (swap), it is
2434  * rarely useful to check for memory exhaustion, but there may be
2435  * some specialized cases where the return value of is_error() is
2436  * useful.) If this exception is thrown, the task will not start
2437  * (which also means that the 'when' and 'fail' callbacks will not
2438  * execute).
2439  * @note 1. This method will also throw if the copy or move
2440  * constructor of the 'func', 'when' or 'fail' callable objects
2441  * throws. If such an exception is thrown, the task will not start
2442  * (which also means that the 'when' and 'fail' callbacks will not
2443  * execute).
2444  * @note 2. If any of the callable objects passed to this method have
2445  * both const and non-const operator()() methods, the non-const
2446  * version will be called even if the callable object passed is a
2447  * const object.
2448  * @note 3. If a 'when_releaser' or a 'fail_releaser' object is
2449  * provided, it is in theory possible (if memory is exhausted and the
2450  * system throws in that case) that an internal SafeEmitterArg object
2451  * will throw std::bad_alloc when emitting/executing the 'when' or
2452  * 'fail' callback in the glib main loop, with the result that the
2453  * relevant callback will not execute (instead the exception will be
2454  * consumed and a g_critical() warning will be issued). This is
2455  * rarely of any relevance because glib will abort the program if it
2456  * is itself unable to obtain memory from the operating system.
2457  * However, where it is relevant, design the program so that it is
2458  * not necessary to provide a releaser object.
2459  *
2460  * Since 2.1.0
2461  */
2462  // we need to use enable_if so that where this function is passed
2463  // unique_ptr's holding non-const Callback::CallbackArg objects, or
2464  // some other convertible object, this templated overload is dropped
2465  // from the overload set, in order to support the unique_ptr
2466  // overloads of this function. This overload calls into the version
2467  // of this function taking CallbackArg objects by unique_ptr in
2468  // order to perform type erasure.
2469  template <class When, class Fail, class Func,
2470  class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value
2471  && !std::is_convertible<Fail, std::unique_ptr<const Callback::Callback>>::value>::type>
2472  void make_task_when_full(When&& when,
2473  Cgu::Releaser* when_releaser,
2474  Fail&& fail,
2475  Cgu::Releaser* fail_releaser,
2476  gint priority,
2477  GMainContext* context,
2478  Func&& func) {
2479  // this method will fail to compile if Ret is a reference type:
2480  // that is a feature, not a bug, as a function returning a
2481  // reference lacks referential transparency, is unlikely to be
2482  // thread-safe and is unsuitable for use as a task function
2483  typedef decltype(func()) Ret;
2484  std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2485  Callback::lambda<const Ret&>(std::forward<When>(when))
2486  );
2487  std::unique_ptr<const Callback::Callback> fail_ptr(
2488  Callback::lambda<>(std::forward<Fail>(fail))
2489  );
2490  make_task_when_full(std::move(when_ptr),
2491  when_releaser,
2492  std::move(fail_ptr),
2493  fail_releaser,
2494  priority,
2495  context,
2496  std::forward<Func>(func));
2497  }
2498 
2499  /**
2500  * This is an abbreviated version of make_task_when_full(), which is
2501  * for use when it is known that invocation of the callable object
2502  * passed to this method and the move constructor (or if it has none,
2503  * the copy constructor) of that object's return value do not throw
2504  * anything other than std::bad_alloc, and the user is not interested
2505  * in std::bad_alloc and does not need a Cgu::Releaser object for the
2506  * 'when' callback (which is likely to cover the majority of uses,
2507  * particularly when composing tasks using glib because glib
2508  * terminates the program if it is unable to obtain memory).
2509  *
2510  * Like make_task_when_full(), this method is a wrapper which takes a
2511  * callable object which returns a value, and constructs a
2512  * TaskManager task which will execute that object by calling
2513  * add_task() with an appropriate callback object, and causes the
2514  * 'when' callback passed as an argument to this method to be
2515  * executed by a glib main loop if and when the task finishes
2516  * correctly - the 'when' callback is passed the callable object's
2517  * return value when it is invoked. It is thread safe (any thread
2518  * may call this method, including another task running on the
2519  * TaskManager object). Apart from the absence of a 'one thread per
2520  * task' model, this method therefore provides a similar interface to
2521  * the one provided by Cgu::Thread::Future. See the documentation on
2522  * add_task() for further information about how task execution works.
2523  *
2524  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2525  * in the main loop.
2526  *
2527  * There is a similar make_task_compose() function which has the
2528  * callable object to be executed as a task as its first argument and
2529  * the 'when' callback as its last argument, in order to aid task
2530  * composition.
2531  *
2532  * @param when A callback which will be executed if and when the
2533  * callable object passed to this method finishes correctly. The
2534  * callback is passed that object's return value when it is invoked.
2535  * If an exception propagates from the 'when' callback, this will be
2536  * consumed and a g_critical() warning will be issued. The callback
2537  * will execute in the glib main loop whose GMainContext object is
2538  * passed to the 'context' argument of this method.
2539  * @param context The glib main context of the main loop in which the
2540  * 'when' callback is to be executed. A value 0/NULL/nullptr will
2541  * cause the callback to be executed in the main program loop.
2542  * @param f The callable object to be executed as a task, such as
2543  * formed by a lambda expression or the result of std::bind. It
2544  * should return a value (it cannot return void). It must be fully
2545  * bound (that is, it must take no arguments when called). If an
2546  * exception propagates from the task, the exception will be consumed
2547  * and (if the thrown object's type is not Cgu::Thread::Exit) a
2548  * g_critical() warning will be issued.
2549  * @exception std::bad_alloc This exception will be thrown if memory
2550  * is exhausted and the system throws in that case. (On systems with
2551  * over-commit/lazy-commit combined with virtual memory (swap), it is
2552  * rarely useful to check for memory exhaustion). See also the
2553  * documentation for the get_max_tasks() method about the possibility
2554  * of std::length_error being thrown. If std::bad_alloc or
2555  * std::length_error is thrown, the task will not start (which also
2556  * means that the 'when' callback will not execute).
2557  * @exception Cgu::Thread::TaskError This exception will be thrown if
2558  * stop_all() has previously been called. It will also be thrown if
2559  * is_error() would return true because this class's internal thread
2560  * pool loop implementation has thrown std::bad_alloc, or a thread
2561  * has failed to start correctly. (On systems with
2562  * over-commit/lazy-commit combined with virtual memory (swap), it is
2563  * rarely useful to check for memory exhaustion, but there may be
2564  * some specialized cases where the return value of is_error() is
2565  * useful.) If this exception is thrown, the task will not start
2566  * (which also means that the 'when' callback will not execute).
2567  * @note 1. This method will also throw if the copy or move
2568  * constructor of the callable object throws. If such an exception
2569  * is thrown, the task will not start (which also means that the
2570  * 'when' callback will not execute).
2571  * @note 2. If the callable object passed as an argument has both
2572  * const and non-const operator()() methods, the non-const version
2573  * will be called even if the callable object passed is a const
2574  * object.
2575  * @note 3. As mentioned in describing 'f' above, if 'f' exits by
2576  * throwing an exception the exception will be consumed and (if the
2577  * thrown object's type is not Cgu::Thread::Exit) a g_critical()
2578  * warning will be issued. The same will occur if the move
2579  * constructor (or if it has none, the copy constructor) of the
2580  * return value of 'f' throws or if the internal implementation of
2581  * this wrapper throws std::bad_alloc on executing 'f'.
2582  *
2583  * Since 2.0.14
2584  */
2585  template <class Ret, class Func>
2586  void make_task_when(std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when,
2587  GMainContext* context,
2588  Func&& f) {
2589  make_task_when_full(std::move(when),
2590  0,
2591  std::unique_ptr<const Cgu::Callback::Callback>(),
2592  0,
2593  G_PRIORITY_DEFAULT,
2594  context,
2595  std::forward<Func>(f));
2596  }
2597 
2598  /**
2599  * This is an abbreviated version of make_task_when_full(), which is
2600  * for use when it is known that invocation of the callable object
2601  * passed to the 'func' argument of this method and the move
2602  * constructor (or if it has none, the copy constructor) of that
2603  * object's return value do not throw anything other than
2604  * std::bad_alloc, and the user is not interested in std::bad_alloc
2605  * and does not need a Cgu::Releaser object for the 'when' callback
2606  * (which is likely to cover the majority of uses, particularly when
2607  * composing tasks using glib because glib terminates the program if
2608  * it is unable to obtain memory).
2609  *
2610  * Like make_task_when_full(), this method is a wrapper which takes a
2611  * callable object which returns a value as its 'func' argument, and
2612  * constructs a TaskManager task which will execute that object by
2613  * calling add_task() with an appropriate callback object, and causes
2614  * the 'when' callback passed as an argument to this method to be
2615  * executed by a glib main loop if and when the task finishes
2616  * correctly - the 'when' callback is passed the return value of the
2617  * 'func' argument when it is invoked. It is thread safe (any thread
2618  * may call this method, including another task running on the
2619  * TaskManager object). Apart from the absence of a 'one thread per
2620  * task' model, this method therefore provides a similar interface to
2621  * the one provided by Cgu::Thread::Future. See the documentation on
2622  * add_task() for further information about how task execution works.
2623  *
2624  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2625  * in the main loop.
2626  *
2627  * There is a similar make_task_compose() function which has the
2628  * callable object to be executed as a task as its first argument and
2629  * the 'when' callback as its last argument, in order to aid task
2630  * composition.
2631  *
2632  * @param when A callable object (such as formed by a lambda
2633  * expression or the result of std::bind) which will be executed if
2634  * and when the 'func' object passed to this method finishes
2635  * correctly. The 'when' callback is passed that objects's return
2636  * value when invoked, and should take a single unbound argument,
2637  * namely a reference to const of the type of that return value. If
2638  * an exception propagates from the 'when' callback, this will be
2639  * consumed and a g_critical() warning will be issued. The callback
2640  * will execute in the glib main loop whose GMainContext object is
2641  * passed to the 'context' argument of this method.
2642  * @param context The glib main context of the main loop in which the
2643  * 'when' callback is to be executed. A value 0/NULL/nullptr will
2644  * cause the callback to be executed in the main program loop.
2645  * @param func The callable object to be executed as a task, such as
2646  * formed by a lambda expression or the result of std::bind. It
2647  * should return a value (it cannot return void). It must be fully
2648  * bound (that is, it must take no arguments when called). If an
2649  * exception propagates from the task, the exception will be consumed
2650  * and (if the thrown object's type is not Cgu::Thread::Exit) a
2651  * g_critical() warning will be issued.
2652  * @exception std::bad_alloc This exception will be thrown if memory
2653  * is exhausted and the system throws in that case. (On systems with
2654  * over-commit/lazy-commit combined with virtual memory (swap), it is
2655  * rarely useful to check for memory exhaustion). See also the
2656  * documentation for the get_max_tasks() method about the possibility
2657  * of std::length_error being thrown. If std::bad_alloc or
2658  * std::length_error is thrown, the task will not start (which also
2659  * means that the 'when' callback will not execute).
2660  * @exception Cgu::Thread::TaskError This exception will be thrown if
2661  * stop_all() has previously been called. It will also be thrown if
2662  * is_error() would return true because this class's internal thread
2663  * pool loop implementation has thrown std::bad_alloc, or a thread
2664  * has failed to start correctly. (On systems with
2665  * over-commit/lazy-commit combined with virtual memory (swap), it is
2666  * rarely useful to check for memory exhaustion, but there may be
2667  * some specialized cases where the return value of is_error() is
2668  * useful.) If this exception is thrown, the task will not start
2669  * (which also means that the 'when' callback will not execute).
2670  * @note 1. This method will also throw if the copy or move
2671  * constructor of the 'func' or 'when' callable objects throws. If
2672  * such an exception is thrown, the task will not start (which also
2673  * means that the 'when' callback will not execute).
2674  * @note 2. If any of the callable objects passed to this method have
2675  * both const and non-const operator()() methods, the non-const
2676  * version will be called even if the callable object passed is a
2677  * const object.
2678  * @note 3. As mentioned in describing 'func' above, if 'func' exits
2679  * by throwing an exception the exception will be consumed and (if
2680  * the thrown object's type is not Cgu::Thread::Exit) a g_critical()
2681  * warning will be issued. The same will occur if the move
2682  * constructor (or if it has none, the copy constructor) of the
2683  * return value of 'func' throws or if the internal implementation of
2684  * this wrapper throws std::bad_alloc on executing 'func'.
2685  *
2686  * Since 2.1.0
2687  */
2688  // we need to use enable_if so that where this function is passed a
2689  // unique_ptr holding a non-const Callback::CallbackArg object, or
2690  // some other convertible object, this templated overload is dropped
2691  // from the overload set, in order to support the unique_ptr
2692  // overloads of this function. This overload calls into the version
2693  // of this function taking a CallbackArg object by unique_ptr in
2694  // order to perform type erasure.
2695  template <class When, class Func,
2696  class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value>::type>
2697  void make_task_when(When&& when,
2698  GMainContext* context,
2699  Func&& func) {
2700  // this method will fail to compile if Ret is a reference type:
2701  // that is a feature, not a bug, as a function returning a
2702  // reference lacks referential transparency, is unlikely to be
2703  // thread-safe and is unsuitable for use as a task function
2704  typedef decltype(func()) Ret;
2705  std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2706  Callback::lambda<const Ret&>(std::forward<When>(when))
2707  );
2708  make_task_when_full(std::move(when_ptr),
2709  0,
2710  std::unique_ptr<const Cgu::Callback::Callback>(),
2711  0,
2712  G_PRIORITY_DEFAULT,
2713  context,
2714  std::forward<Func>(func));
2715  }
2716 
2717  /**
2718  * This is an abbreviated version of make_task_when_full(), which is
2719  * for use when it is known that invocation of the callable object
2720  * passed to this method and the move constructor (or if it has none,
2721  * the copy constructor) of that object's return value do not throw
2722  * anything other than std::bad_alloc, and the user is not interested
2723  * in std::bad_alloc and does not need a Cgu::Releaser object for the
2724  * 'when' callback (which is likely to cover the majority of uses,
2725  * particularly when composing tasks using glib because glib
2726  * terminates the program if it is unable to obtain memory).
2727  *
2728  * This method does the same as the version of make_task_when()
2729  * taking a callable object, except that this method takes that
2730  * object as its first argument and the 'when' callback as its last
2731  * argument in order to aid task composition, and in particular so
2732  * tasks compose in user code in a visually ordered manner.
2733  *
2734  * More particularly, like make_task_when_full(), this method is a
2735  * wrapper which takes a callable object which returns a value, and
2736  * constructs a TaskManager task which will execute that object by
2737  * calling add_task() with an appropriate callback object, and causes
2738  * the 'when' callback passed as an argument to this method to be
2739  * executed by a glib main loop if and when the task finishes
2740  * correctly - the 'when' callback is passed the callable object's
2741  * return value when it is invoked. It is thread safe (any thread
2742  * may call this method, including another task running on the
2743  * TaskManager object). Apart from the absence of a 'one thread per
2744  * task' model, this method therefore provides a similar interface to
2745  * the one provided by Cgu::Thread::Future. See the documentation on
2746  * add_task() for further information about how task execution works.
2747  *
2748  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2749  * in the main loop.
2750  *
2751  * @param f The callable object to be executed as a task, such as
2752  * formed by a lambda expression or the result of std::bind. It
2753  * should return a value (it cannot return void). It must be fully
2754  * bound (that is, it must take no arguments when called). If an
2755  * exception propagates from the task, the exception will be consumed
2756  * and (if the thrown object's type is not Cgu::Thread::Exit) a
2757  * g_critical() warning will be issued.
2758  * @param context The glib main context of the main loop in which the
2759  * 'when' callback is to be executed. A value 0/NULL/nullptr will
2760  * cause the callback to be executed in the main program loop.
2761  * @param when A callback which will be executed if and when the
2762  * callable object passed to this method finishes correctly. The
2763  * callback is passed that object's return value when it is invoked.
2764  * If an exception propagates from the 'when' callback, this will be
2765  * consumed and a g_critical() warning will be issued. The callback
2766  * will execute in the glib main loop whose GMainContext object is
2767  * passed to the 'context' argument of this method.
2768  * @exception std::bad_alloc This exception will be thrown if memory
2769  * is exhausted and the 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). See also the
2772  * documentation for the get_max_tasks() method about the possibility
2773  * of std::length_error being thrown. If std::bad_alloc or
2774  * std::length_error is thrown, the task will not start (which also
2775  * means that the 'when' callback will not execute).
2776  * @exception Cgu::Thread::TaskError This exception will be thrown if
2777  * stop_all() has previously been called. It will also be thrown if
2778  * is_error() would return true because this class's internal thread
2779  * pool loop implementation has thrown std::bad_alloc, or a thread
2780  * has failed to start correctly. (On systems with
2781  * over-commit/lazy-commit combined with virtual memory (swap), it is
2782  * rarely useful to check for memory exhaustion, but there may be
2783  * some specialized cases where the return value of is_error() is
2784  * useful.) If this exception is thrown, the task will not start
2785  * (which also means that the 'when' callback will not execute).
2786  * @note 1. This method will also throw if the copy or move
2787  * constructor of the callable object throws. If such an exception
2788  * is thrown, the task will not start (which also means that the
2789  * 'when' callback will not execute).
2790  * @note 2. If the callable object passed as an argument has both
2791  * const and non-const operator()() methods, the non-const version
2792  * will be called even if the callable object passed is a const
2793  * object.
2794  * @note 3. As mentioned in describing 'f' above, if 'f' exits by
2795  * throwing an exception the exception will be consumed and (if the
2796  * thrown object's type is not Cgu::Thread::Exit) a g_critical()
2797  * warning will be issued. The same will occur if the move
2798  * constructor (or if it has none, the copy constructor) of the
2799  * return value of 'f' throws or if the internal implementation of
2800  * this wrapper throws std::bad_alloc on executing 'f'.
2801  *
2802  * Since 2.0.14
2803  */
2804  template <class Ret, class Func>
2805  void make_task_compose(Func&& f,
2806  GMainContext* context,
2807  std::unique_ptr<const Cgu::Callback::CallbackArg<const Ret&>> when) {
2808  make_task_when_full(std::move(when),
2809  0,
2810  std::unique_ptr<const Cgu::Callback::Callback>(),
2811  0,
2812  G_PRIORITY_DEFAULT,
2813  context,
2814  std::forward<Func>(f));
2815  }
2816 
2817  /**
2818  * This is an abbreviated version of make_task_when_full(), which is
2819  * for use when it is known that invocation of the callable object
2820  * passed to the 'func' argument of this method and the move
2821  * constructor (or if it has none, the copy constructor) of that
2822  * object's return value do not throw anything other than
2823  * std::bad_alloc, and the user is not interested in std::bad_alloc
2824  * and does not need a Cgu::Releaser object for the 'when' callback
2825  * (which is likely to cover the majority of uses, particularly when
2826  * composing tasks using glib because glib terminates the program if
2827  * it is unable to obtain memory).
2828  *
2829  * This method does the same as make_task_when(), except that this
2830  * method takes the callable object to be executed as a task as its
2831  * first argument and the 'when' callback as its last argument in
2832  * order to aid task composition, and in particular so tasks compose
2833  * in user code in a visually ordered manner.
2834  *
2835  * More particularly, like make_task_when_full(), this method is a
2836  * wrapper which takes a callable object which returns a value as its
2837  * 'func' argument, and constructs a TaskManager task which will
2838  * execute that object by calling add_task() with an appropriate
2839  * callback object, and causes the 'when' callback passed as an
2840  * argument to this method to be executed by a glib main loop if and
2841  * when the task finishes correctly - the 'when' callback is passed
2842  * the return value of the 'func' argument when it is invoked. It is
2843  * thread safe (any thread may call this method, including another
2844  * task running on the TaskManager object). Apart from the absence
2845  * of a 'one thread per task' model, this method therefore provides a
2846  * similar interface to the one provided by Cgu::Thread::Future. See
2847  * the documentation on add_task() for further information about how
2848  * task execution works.
2849  *
2850  * The 'when' callback will execute with G_PRIORITY_DEFAULT priority
2851  * in the main loop.
2852  *
2853  * @param func The callable object to be executed as a task, such as
2854  * formed by a lambda expression or the result of std::bind. It
2855  * should return a value (it cannot return void). It must be fully
2856  * bound (that is, it must take no arguments when called). If an
2857  * exception propagates from the task, the exception will be consumed
2858  * and (if the thrown object's type is not Cgu::Thread::Exit) a
2859  * g_critical() warning will be issued.
2860  * @param context The glib main context of the main loop in which the
2861  * 'when' callback is to be executed. A value 0/NULL/nullptr will
2862  * cause the callback to be executed in the main program loop.
2863  * @param when A callable object (such as formed by a lambda
2864  * expression or the result of std::bind) which will be executed if
2865  * and when the 'func' object passed to this method finishes
2866  * correctly. The 'when' callback is passed that objects's return
2867  * value when invoked, and should take a single unbound argument,
2868  * namely a reference to const of the type of that return value. If
2869  * an exception propagates from the 'when' callback, this will be
2870  * consumed and a g_critical() warning will be issued. The callback
2871  * will execute in the glib main loop whose GMainContext object is
2872  * passed to the 'context' argument of this method.
2873  * @exception std::bad_alloc This exception will be thrown if memory
2874  * is exhausted and the system throws in that case. (On systems with
2875  * over-commit/lazy-commit combined with virtual memory (swap), it is
2876  * rarely useful to check for memory exhaustion). See also the
2877  * documentation for the get_max_tasks() method about the possibility
2878  * of std::length_error being thrown. If std::bad_alloc or
2879  * std::length_error is thrown, the task will not start (which also
2880  * means that the 'when' callback will not execute).
2881  * @exception Cgu::Thread::TaskError This exception will be thrown if
2882  * stop_all() has previously been called. It will also be thrown if
2883  * is_error() would return true because this class's internal thread
2884  * pool loop implementation has thrown std::bad_alloc, or a thread
2885  * has failed to start correctly. (On systems with
2886  * over-commit/lazy-commit combined with virtual memory (swap), it is
2887  * rarely useful to check for memory exhaustion, but there may be
2888  * some specialized cases where the return value of is_error() is
2889  * useful.) If this exception is thrown, the task will not start
2890  * (which also means that the 'when' callback will not execute).
2891  * @note 1. This method will also throw if the copy or move
2892  * constructor of the 'func' or 'when' callable objects throws. If
2893  * such an exception is thrown, the task will not start (which also
2894  * means that the 'when' callback will not execute).
2895  * @note 2. If any of the callable objects passed to this method have
2896  * both const and non-const operator()() methods, the non-const
2897  * version will be called even if the callable object passed is a
2898  * const object.
2899  * @note 3. As mentioned in describing 'func' above, if 'func' exits
2900  * by throwing an exception the exception will be consumed and (if
2901  * the thrown object's type is not Cgu::Thread::Exit) a g_critical()
2902  * warning will be issued. The same will occur if the move
2903  * constructor (or if it has none, the copy constructor) of the
2904  * return value of 'func' throws or if the internal implementation of
2905  * this wrapper throws std::bad_alloc on executing 'func'.
2906  *
2907  * Since 2.1.0
2908  */
2909  // we need to use enable_if so that where this function is passed a
2910  // unique_ptr holding a non-const Callback::CallbackArg object, or
2911  // some other convertible object, this templated overload is dropped
2912  // from the overload set, in order to support the unique_ptr
2913  // overloads of this function. This overload calls into the version
2914  // of this function taking a CallbackArg object by unique_ptr in
2915  // order to perform type erasure.
2916  template <class Func, class When,
2917  class = typename std::enable_if<!std::is_convertible<When, std::unique_ptr<const Callback::CallbackArg<const typename std::result_of<Func()>::type&>>>::value>::type>
2918  void make_task_compose(Func&& func,
2919  GMainContext* context,
2920  When&& when) {
2921  // this method will fail to compile if Ret is a reference type:
2922  // that is a feature, not a bug, as a function returning a
2923  // reference lacks referential transparency, is unlikely to be
2924  // thread-safe and is unsuitable for use as a task function
2925  typedef decltype(func()) Ret;
2926  std::unique_ptr<const Callback::CallbackArg<const Ret&>> when_ptr(
2927  Callback::lambda<const Ret&>(std::forward<When>(when))
2928  );
2929  make_task_when_full(std::move(when_ptr),
2930  0,
2931  std::unique_ptr<const Cgu::Callback::Callback>(),
2932  0,
2933  G_PRIORITY_DEFAULT,
2934  context,
2935  std::forward<Func>(func));
2936  }
2937 
2938  /**
2939  * This is a wrapper which takes a callable object (such as a
2940  * std::function object, a lambda or the return value of std::bind),
2941  * and constructs a TaskManager task which will execute that object
2942  * by calling add_task() with an appropriate callback representing a
2943  * std::packaged_task object, and returns a std::future object which
2944  * will provide the value (if any) that the callable object returns.
2945  * It is thread safe: any thread may call this method, including
2946  * another task running on the TaskManager object, but see the
2947  * introductory remarks about the use of the TaskManager::IncHandle
2948  * scoped handle class where a task running on a TaskManager object
2949  * is to block on one of its sub-tasks. See also the documentation
2950  * on add_task() for further information about how task execution
2951  * works.
2952  *
2953  * If the callable object passed to this method exits by throwing an
2954  * exception (including Thread::Exit), that exception is stored in
2955  * the shared state of std::packaged_task, and will be rethrown when
2956  * get() is called on the returned std::future object. The callable
2957  * object may return void, in which case the std::future<void> object
2958  * returned by this method would be used for the purpose only of
2959  * obtaining an exception, or of "joining" on the completed task.
2960  *
2961  * One of the (perhaps odd) side effects of the specification of
2962  * std::async() in C++11/14 is that the question whether a
2963  * std::future object's destructor blocks until completion of its
2964  * associated task depends on whether it was constructed by a call to
2965  * std::async(). As the return value of this method is obtained from
2966  * std::packaged_task and not by a call to std::async(), its
2967  * destructor will not block. If the returned std::future object is
2968  * allowed to go out of scope before the task completes and without
2969  * moving to another std::future object, the task will run to
2970  * completion (unless it throws a prior exception), but its return
2971  * value will be discarded.
2972  *
2973  * @param f The callable object, such as formed by a lambda
2974  * expression or the result of std::bind, to be executed via
2975  * std::packaged_task by the TaskManager object.
2976  * @return A std::future object representing the shared state of a
2977  * std::packaged_task object constructed to execute the task, from
2978  * which the result of the task can be obtained.
2979  * @exception std::bad_alloc This exception will be thrown if memory
2980  * is exhausted and the system throws in that case. (On systems with
2981  * over-commit/lazy-commit combined with virtual memory (swap), it is
2982  * rarely useful to check for memory exhaustion). See also the
2983  * documentation for the get_max_tasks() method about the possibility
2984  * of std::length_error being thrown. If std::bad_alloc or
2985  * std::length_error is thrown, the task will not start.
2986  * @exception Cgu::Thread::TaskError This exception will be thrown if
2987  * stop_all() has previously been called. It will also be thrown if
2988  * is_error() would return true because this class's internal thread
2989  * pool loop implementation has thrown std::bad_alloc, or a thread
2990  * has failed to start correctly. (On systems with
2991  * over-commit/lazy-commit combined with virtual memory (swap), it is
2992  * rarely useful to check for memory exhaustion, but there may be
2993  * some specialized cases where the return value of is_error() is
2994  * useful.) If this exception is thrown, the task will not start.
2995  * @note This method will also throw if the copy or move
2996  * constructor of the callable object throws, or the move constructor
2997  * of std::packaged_task throws. If such an exception is thrown, the
2998  * task will not start.
2999  *
3000  * Since 2.2.4
3001  */
3002  template <class Func>
3003  auto make_task_packaged(Func&& f) -> std::future<decltype(f())> {
3004 
3005  // TODO: this is a work-around for gcc < 4.7, which has a bug
3006  // which requires a function whose return value is determined by
3007  // decltype, such as make_task_packaged(Func&&), to be inline. At
3008  // a suitable API/ABI break when gcc requirements are updated,
3009  // this should be moved to task_manager.tpp.
3010 
3011  // this method will fail to compile if Ret is a reference type:
3012  // that is a feature, not a bug, as a function returning a
3013  // reference lacks referential transparency, is unlikely to be
3014  // thread-safe and is unsuitable for use as a task function
3015  typedef decltype(f()) Ret;
3016 
3017  std::packaged_task<Ret()> task{std::forward<Func>(f)};
3018  std::future<Ret> ret{task.get_future()};
3019  add_task(std::move(task));
3020 
3021  return ret;
3022  }
3023 
3024  /**
3025  * This method is similar to make_task_when_full(): it takes a
3026  * callable object as its 'func' argument (such as a std::function
3027  * object, a lambda or the return value of std::bind), and constructs
3028  * a TaskManager task which will execute that object by calling
3029  * add_task() with an appropriate callback object, and causes the
3030  * 'when' callback passed as an argument to this method to be
3031  * executed by a glib main loop when the task finishes. However,
3032  * unlike make_task_when_full(), it constructs a std::packaged_task
3033  * object to execute the task, and instead of passing the return
3034  * value of 'func' directly as an argument to the 'when' callback, it
3035  * passes a non-const reference to a std::future object of the return
3036  * type: so if 'func' returns a std::string object, the 'when'
3037  * callback should take a 'std::future<std::string>&' argument. The
3038  * main purpose of this is to store any exception thrown by 'func'
3039  * (or by the move or copy constructor of its return value) in the
3040  * std::packaged_task object's shared state, so that it can be
3041  * obtained by the 'when' callback by calling std::future::get(). In
3042  * addition, subject to note 3 below this method's task wrapper will
3043  * never be in the position of consuming an internal std::bad_alloc
3044  * exception (although this method might throw std::bad_alloc).
3045  * Amongst other things, this dispenses with the need for a 'fail'
3046  * callback (at a very slight cost to efficiency compared with
3047  * make_task_when_full()).
3048  *
3049  * The callable object comprising the 'func' argument may return
3050  * void, if the purpose of the 'when' callback is only to deal in the
3051  * glib main loop with any exception thrown by 'func', or to do
3052  * something in the glib main loop dependent on the task having
3053  * finished but not on a value returned by it.
3054  *
3055  * A call to std::future::get() on the passed std::future object will
3056  * never block, because the 'when' callback is only invoked after the
3057  * task has finished (successfully or by throwing an exception).
3058  *
3059  * This method is thread safe (any thread may call it, including
3060  * another task running on the TaskManager object). See the
3061  * documentation on add_task() for further information about how task
3062  * execution works.
3063  *
3064  * Note that if a releaser is provided for the 'when' callback, this
3065  * is passed by pointer and not by reference (this is so that a NULL
3066  * pointer can indicate that no releaser is to be provided). If
3067  * provided, a releaser will enable automatic disconnection of the
3068  * 'when' callback if the object of which the releaser is a member is
3069  * destroyed. For this to be race free, the lifetime of that object
3070  * must be controlled by the thread in whose main loop the 'when'
3071  * callback will execute.
3072  *
3073  * There is an overload of this method which takes only three
3074  * arguments - the 'when' callback, a context argument and the
3075  * callable object to be run as a task, which is analogous to
3076  * make_task_when(). It is shorthand for cases where the 'when'
3077  * callback is to be executed without a releaser and with
3078  * G_PRIORITY_DEFAULT priority.
3079  *
3080  * @param when A callable object (such as formed by a lambda
3081  * expression or the result of std::bind) which will be executed when
3082  * the 'func' object passed to this method finishes, either by
3083  * executing normally or by throwing an exception. The 'when'
3084  * callback should take a single unbound argument, namely a non-const
3085  * reference to a std::future object for the type of the return value
3086  * of the 'func' object. If an exception propagates from the 'when'
3087  * callback, this will be consumed and a g_critical() warning will be
3088  * issued. The callback will execute in the glib main loop whose
3089  * GMainContext object is passed to the 'context' argument of this
3090  * method.
3091  * @param when_releaser A pointer to a Releaser object for automatic
3092  * disconnection of the 'when' callback before it executes in a main
3093  * loop (mainly relevant if the callback calls a non-static member
3094  * function of an object which may be destroyed before the callback
3095  * executes). A value of 0/NULL/nullptr indicates no releaser.
3096  * @param priority The priority to be given in the main loop to the
3097  * 'when' callback. In ascending order of priorities, priorities are
3098  * G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE,
3099  * G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. This determines the order
3100  * in which the callback will appear in the event list in the main
3101  * loop, not the priority which the OS will adopt.
3102  * @param context The glib main context of the main loop in which the
3103  * 'when' callback is to be executed. A value 0/NULL/nullptr will
3104  * cause the callback to be executed in the main program loop.
3105  * @param func The callable object to be executed as a task, such as
3106  * formed by a lambda expression or the result of std::bind. It must
3107  * be fully bound (that is, it must take no arguments when called).
3108  * If an exception propagates from the task, the exception will be
3109  * stored in the shared state of a std::packaged_task object and made
3110  * available to the 'when' callback via std::future::get().
3111  * @exception std::bad_alloc This exception will be thrown if memory
3112  * is exhausted and the system throws in that case. (On systems with
3113  * over-commit/lazy-commit combined with virtual memory (swap), it is
3114  * rarely useful to check for memory exhaustion). See also the
3115  * documentation for the get_max_tasks() method about the possibility
3116  * of std::length_error being thrown. If std::bad_alloc or
3117  * std::length_error is thrown, the task will not start (which also
3118  * means that the 'when' callback will not execute).
3119  * @exception Cgu::Thread::TaskError This exception will be thrown if
3120  * stop_all() has previously been called. It will also be thrown if
3121  * is_error() would return true because this class's internal thread
3122  * pool loop implementation has thrown std::bad_alloc, or a thread
3123  * has failed to start correctly. (On systems with
3124  * over-commit/lazy-commit combined with virtual memory (swap), it is
3125  * rarely useful to check for memory exhaustion, but there may be
3126  * some specialized cases where the return value of is_error() is
3127  * useful.) If this exception is thrown, the task will not start
3128  * (which also means that the 'when' callback will not execute).
3129  * @note 1. This method will also throw if the copy or move
3130  * constructor of the 'func' or 'when' callable objects throws. If
3131  * such an exception is thrown, the task will not start (which also
3132  * means that the 'when' callback will not execute).
3133  * @note 2. If any of the callable objects passed to this method have
3134  * both const and non-const operator()() methods, the non-const
3135  * version will be called even if the callable object passed is a
3136  * const object.
3137  * @note 3. If a 'when_releaser' object is provided, it is in theory
3138  * possible (if memory is exhausted and the system throws in that
3139  * case) that an internal SafeEmitterArg object will throw
3140  * std::bad_alloc when emitting/executing the 'when' callback in the
3141  * glib main loop, with the result that the relevant callback will
3142  * not execute (instead the exception will be consumed and a
3143  * g_critical() warning will be issued). This is rarely of any
3144  * relevance because glib will abort the program if it is itself
3145  * unable to obtain memory from the operating system. However, where
3146  * it is relevant, design the program so that it is not necessary to
3147  * provide a releaser object.
3148  *
3149  * Since 2.2.5
3150  */
3151  template <class When, class Func>
3152  void make_task_packaged_when(When&& when,
3153  Cgu::Releaser* when_releaser,
3154  gint priority,
3155  GMainContext* context,
3156  Func&& func);
3157 
3158  /**
3159  * This overload of make_task_packaged_when() taking three arguments
3160  * is an abbreviated version of the one taking five arguments. It is
3161  * for use where the 'when' callback is to be executed without a
3162  * releaser and with G_PRIORITY_DEFAULT priority.
3163  *
3164  * It is similar to make_task_when(): it takes a callable object as
3165  * its 'func' argument (such as a std::function object, a lambda or
3166  * the return value of std::bind), and constructs a TaskManager task
3167  * which will execute that object by calling add_task() with an
3168  * appropriate callback object, and causes the 'when' callback passed
3169  * as an argument to this method to be executed by a glib main loop
3170  * when the task finishes. However, unlike make_task_when(), it
3171  * constructs a std::packaged_task object to execute the task, and
3172  * instead of passing the return value of 'func' directly as an
3173  * argument to the 'when' callback, it passes a non-const reference
3174  * to a std::future object of the return type: so if 'func' returns a
3175  * std::string object, the 'when' callback should take a
3176  * 'std::future<std::string>&' argument. The main purpose of this is
3177  * to store any exception thrown by 'func' (or by the move or copy
3178  * constructor of its return value) in the std::packaged_task
3179  * object's shared state, so that it can be obtained by the 'when'
3180  * callback by calling std::future::get(). In addition, this
3181  * method's task wrapper will never be in the position of consuming
3182  * an internal std::bad_alloc exception (although this method might
3183  * throw std::bad_alloc).
3184  *
3185  * The callable object comprising the 'func' argument may return
3186  * void, if the purpose of the 'when' callback is only to deal in the
3187  * glib main loop with any exception thrown by 'func', or to do
3188  * something in the glib main loop dependent on the task having
3189  * finished but not on a value returned by it.
3190  *
3191  * A call to std::future::get() on the passed std::future object will
3192  * never block, because the 'when' callback is only invoked after the
3193  * task has finished (successfully or by throwing an exception).
3194  *
3195  * This method is thread safe (any thread may call it, including
3196  * another task running on the TaskManager object). See the
3197  * documentation on add_task() for further information about how task
3198  * execution works.
3199  *
3200  * @param when A callable object (such as formed by a lambda
3201  * expression or the result of std::bind) which will be executed when
3202  * the 'func' object passed to this method finishes, either by
3203  * executing normally or by throwing an exception. The 'when'
3204  * callback should take a single unbound argument, namely a non-const
3205  * reference to a std::future object for the type of the return value
3206  * of the 'func' object. If an exception propagates from the 'when'
3207  * callback, this will be consumed and a g_critical() warning will be
3208  * issued. The callback will execute in the glib main loop whose
3209  * GMainContext object is passed to the 'context' argument of this
3210  * method.
3211  * @param context The glib main context of the main loop in which the
3212  * 'when' callback is to be executed. A value 0/NULL/nullptr will
3213  * cause the callback to be executed in the main program loop.
3214  * @param func The callable object to be executed as a task, such as
3215  * formed by a lambda expression or the result of std::bind. It must
3216  * be fully bound (that is, it must take no arguments when called).
3217  * If an exception propagates from the task, the exception will be
3218  * stored in the shared state of a std::packaged_task object and made
3219  * available to the 'when' callback via std::future::get().
3220  * @exception std::bad_alloc This exception will be thrown if memory
3221  * is exhausted and the system throws in that case. (On systems with
3222  * over-commit/lazy-commit combined with virtual memory (swap), it is
3223  * rarely useful to check for memory exhaustion). See also the
3224  * documentation for the get_max_tasks() method about the possibility
3225  * of std::length_error being thrown. If std::bad_alloc or
3226  * std::length_error is thrown, the task will not start (which also
3227  * means that the 'when' callback will not execute).
3228  * @exception Cgu::Thread::TaskError This exception will be thrown if
3229  * stop_all() has previously been called. It will also be thrown if
3230  * is_error() would return true because this class's internal thread
3231  * pool loop implementation has thrown std::bad_alloc, or a thread
3232  * has failed to start correctly. (On systems with
3233  * over-commit/lazy-commit combined with virtual memory (swap), it is
3234  * rarely useful to check for memory exhaustion, but there may be
3235  * some specialized cases where the return value of is_error() is
3236  * useful.) If this exception is thrown, the task will not start
3237  * (which also means that the 'when' callback will not execute).
3238  * @note 1. This method will also throw if the copy or move
3239  * constructor of the 'func' or 'when' callable objects throws. If
3240  * such an exception is thrown, the task will not start (which also
3241  * means that the 'when' callback will not execute).
3242  * @note 2. If any of the callable objects passed to this method have
3243  * both const and non-const operator()() methods, the non-const
3244  * version will be called even if the callable object passed is a
3245  * const object.
3246  *
3247  * Since 2.2.5
3248  */
3249  template <class When, class Func>
3250  void make_task_packaged_when(When&& when,
3251  GMainContext* context,
3252  Func&& func) {
3253  make_task_packaged_when(std::forward<When>(when),
3254  0,
3255  G_PRIORITY_DEFAULT,
3256  context,
3257  std::forward<Func>(func));
3258  }
3259 
3260  /**
3261  * This is the same as the version of make_task_packaged_when()
3262  * taking three arguments, except that it takes the callable object
3263  * to be executed as a task as its first argument and the 'when'
3264  * callback as its last argument in order to aid task composition,
3265  * and in particular so tasks compose in user code in a visually
3266  * ordered manner. It is for use where the 'when' callback is to be
3267  * executed without a releaser and with G_PRIORITY_DEFAULT priority.
3268  *
3269  * It is similar to make_task_compose(): it takes a callable object
3270  * as its 'func' argument (such as a std::function object, a lambda
3271  * or the return value of std::bind), and constructs a TaskManager
3272  * task which will execute that object by calling add_task() with an
3273  * appropriate callback object, and causes the 'when' callback passed
3274  * as an argument to this method to be executed by a glib main loop
3275  * when the task finishes. However, unlike make_task_compose(), it
3276  * constructs a std::packaged_task object to execute the task, and
3277  * instead of passing the return value of 'func' directly as an
3278  * argument to the 'when' callback, it passes a non-const reference
3279  * to a std::future object of the return type: so if 'func' returns a
3280  * std::string object, the 'when' callback should take a
3281  * 'std::future<std::string>&' argument. The main purpose of this is
3282  * to store any exception thrown by 'func' (or by the move or copy
3283  * constructor of its return value) in the std::packaged_task
3284  * object's shared state, so that it can be obtained by the 'when'
3285  * callback by calling std::future::get(). In addition, this
3286  * method's task wrapper will never be in the position of consuming
3287  * an internal std::bad_alloc exception (although this method might
3288  * throw std::bad_alloc).
3289  *
3290  * The callable object comprising the 'func' argument may return
3291  * void, if the purpose of the 'when' callback is only to deal in the
3292  * glib main loop with any exception thrown by 'func', or to do
3293  * something in the glib main loop dependent on the task having
3294  * finished but not on a value returned by it.
3295  *
3296  * A call to std::future::get() on the passed std::future object will
3297  * never block, because the 'when' callback is only invoked after the
3298  * task has finished (successfully or by throwing an exception).
3299  *
3300  * This method is thread safe (any thread may call it, including
3301  * another task running on the TaskManager object). See the
3302  * documentation on add_task() for further information about how task
3303  * execution works.
3304  *
3305  * @param func The callable object to be executed as a task, such as
3306  * formed by a lambda expression or the result of std::bind. It must
3307  * be fully bound (that is, it must take no arguments when called).
3308  * If an exception propagates from the task, the exception will be
3309  * stored in the shared state of a std::packaged_task object and made
3310  * available to the 'when' callback via std::future::get().
3311  * @param context The glib main context of the main loop in which the
3312  * 'when' callback is to be executed. A value 0/NULL/nullptr will
3313  * cause the callback to be executed in the main program loop.
3314  * @param when A callable object (such as formed by a lambda
3315  * expression or the result of std::bind) which will be executed when
3316  * the 'func' object passed to this method finishes, either by
3317  * executing normally or by throwing an exception. The 'when'
3318  * callback should take a single unbound argument, namely a non-const
3319  * reference to a std::future object for the type of the return value
3320  * of the 'func' object. If an exception propagates from the 'when'
3321  * callback, this will be consumed and a g_critical() warning will be
3322  * issued. The callback will execute in the glib main loop whose
3323  * GMainContext object is passed to the 'context' argument of this
3324  * method.
3325  * @exception std::bad_alloc This exception will be thrown if memory
3326  * is exhausted and the system throws in that case. (On systems with
3327  * over-commit/lazy-commit combined with virtual memory (swap), it is
3328  * rarely useful to check for memory exhaustion). See also the
3329  * documentation for the get_max_tasks() method about the possibility
3330  * of std::length_error being thrown. If std::bad_alloc or
3331  * std::length_error is thrown, the task will not start (which also
3332  * means that the 'when' callback will not execute).
3333  * @exception Cgu::Thread::TaskError This exception will be thrown if
3334  * stop_all() has previously been called. It will also be thrown if
3335  * is_error() would return true because this class's internal thread
3336  * pool loop implementation has thrown std::bad_alloc, or a thread
3337  * has failed to start correctly. (On systems with
3338  * over-commit/lazy-commit combined with virtual memory (swap), it is
3339  * rarely useful to check for memory exhaustion, but there may be
3340  * some specialized cases where the return value of is_error() is
3341  * useful.) If this exception is thrown, the task will not start
3342  * (which also means that the 'when' callback will not execute).
3343  * @note 1. This method will also throw if the copy or move
3344  * constructor of the 'func' or 'when' callable objects throws. If
3345  * such an exception is thrown, the task will not start (which also
3346  * means that the 'when' callback will not execute).
3347  * @note 2. If any of the callable objects passed to this method have
3348  * both const and non-const operator()() methods, the non-const
3349  * version will be called even if the callable object passed is a
3350  * const object.
3351  *
3352  * Since 2.2.5
3353  */
3354  template <class When, class Func>
3355  void make_task_packaged_compose(Func&& func,
3356  GMainContext* context,
3357  When&& when) {
3358  make_task_packaged_when(std::forward<When>(when),
3359  0,
3360  G_PRIORITY_DEFAULT,
3361  context,
3362  std::forward<Func>(func));
3363  }
3364 
3365  /**
3366  * If the specified minimum number of threads is greater than 0, this
3367  * constructor will start the required minimum number of threads. If
3368  * glib < 2.32 is installed, g_thread_init() must be called before
3369  * any TaskManager objects are constructed
3370  * @param max The maximum number of threads which the TaskManager
3371  * object will run in the thread pool. If the value passed as this
3372  * argument is less than the value passed as 'min', the maximum
3373  * number of threads will be set to 'min'. A value of 0 is not
3374  * valid, and if this is passed the number will be set to the greater
3375  * of 1 and 'min'.
3376  * @param min The minimum number of threads which the TaskManager
3377  * object will run in the thread pool.
3378  * @param idle The length of time in milliseconds that threads
3379  * greater in number than 'min' and not executing any tasks will
3380  * remain in existence. The default is 10000 (10 seconds).
3381  * @param blocking If true, calls to stop_all() and the destructor
3382  * will not return until the tasks remaining to be executed have
3383  * finished (what is meant by "the tasks remaining to be executed"
3384  * depends on the StopMode setting, for which see the documentation
3385  * on the stop_all() method). If false, stop_all() and the
3386  * destructor will return straight away (which in terms of the
3387  * TaskManager class implementation is safe for the reasons explained
3388  * in the documentation on the destructor).
3389  * @param mode The StopMode setting (either
3390  * Cgu::Thread::TaskManager::wait_for_running or
3391  * Cgu::Thread::TaskManager::wait_for_all) executed when running
3392  * stop_all() or when the destructor is called. See the
3393  * documentation on stop_all() for an explanation of the setting.
3394  * @exception std::bad_alloc This exception might be thrown if memory
3395  * is exhausted and the system throws in that case.
3396  * @exception Cgu::Thread::TaskError This exception will be thrown if
3397  * starting the specified minimum number of threads fails.
3398  * @exception Cgu::Thread::MutexError This exception might be thrown
3399  * if initialisation of the contained mutex fails. (It is often not
3400  * worth checking for this, as it means either memory is exhausted or
3401  * pthread has run out of other resources to create new mutexes.)
3402  * @exception Cgu::Thread::CondError This exception might be thrown
3403  * if initialisation of the contained condition variable fails. (It
3404  * is often not worth checking for this, as it means either memory is
3405  * exhausted or pthread has run out of other resources to create new
3406  * condition variables.)
3407  *
3408  * Since 2.0.12
3409  */
3410  TaskManager(unsigned int max = 8, unsigned int min = 0,
3411  unsigned int idle = 10000, bool blocking = true,
3413 
3414  /**
3415  * The destructor will call stop_all(), unless that method has
3416  * previously been called explicitly without throwing std::bad_alloc.
3417  * If the blocking setting is true, the destructor will not return
3418  * until the tasks remaining to be executed have finished (what is
3419  * meant by "the tasks remaining to be executed" depends on the
3420  * StopMode setting, for which see the documentation on the
3421  * stop_all() method.) If the blocking setting is false, the
3422  * destructor will return straight away: this is safe, because
3423  * TaskManager's internals for running tasks have been implemented
3424  * using reference counting and will not be deleted until all threads
3425  * running on the TaskManager object have finished, although the
3426  * remaining tasks should not attempt to call any of TaskManager's
3427  * methods once the TaskManager object itself has been destroyed.
3428  *
3429  * The destructor is thread safe (any thread can destroy a
3430  * TaskManager object) unless the blocking setting is true, in which
3431  * case no task running on the TaskManager object may destroy the
3432  * TaskManager object. Subject to that, it is not an error for a
3433  * thread to destroy a TaskManager object and so invoke this
3434  * destructor while another thread is already blocking in (if the
3435  * blocking setting is true) or already out of (if the blocking
3436  * setting is false) a call to stop_all() and remaining tasks are
3437  * executing: if blocking, both calls (to stop_all() and to this
3438  * destructor) would safely block together. Any given thread can
3439  * similarly safely follow a non-blocking call to stop_all() by a
3440  * non-blocking call to this destructor even though remaining tasks
3441  * are executing. However, it is an error for a thread to call
3442  * stop_all() after another thread has begun destruction of the
3443  * TaskManager object (that is, after this destructor has been
3444  * entered): there would then be an unresolvable race with the
3445  * destructor.
3446  *
3447  * The destructor will not throw.
3448  *
3449  * If stop_all() has not previously been called explicitly and throws
3450  * std::bad_alloc() when called in this destructor, the exception
3451  * will be caught and consumed, but then the destructor will not
3452  * block even if the blocking setting is true, and if the minimum
3453  * number of threads is not 0 some threads might remain running
3454  * during the entire program duration (albeit safely). Where the
3455  * throwing of std::bad_alloc is a meaningful event (usually it
3456  * isn't) and needs to be guarded against, call stop_all() explicitly
3457  * before this destructor is entered, or use a minimum thread value
3458  * of 0 and allow for the case of the destructor not blocking.
3459  *
3460  * Since 2.0.12
3461  */
3462  ~TaskManager();
3463 
3464 /* Only has effect if --with-glib-memory-slices-compat or
3465  * --with-glib-memory-slices-no-compat option picked */
3467 };
3468 
3469  /**
3470  * @class TaskManager::IncHandle task_manager.h c++-gtk-utils/task_manager.h
3471  * @brief A scoped handle for exception safe incrementing of the
3472  * maximum number of threads that a TaskManager object will run.
3473  * @sa Thread::TaskManager
3474  *
3475  * This class is for use where a task running on a TaskManager object
3476  * is about to make a blocking call. It enables the task to
3477  * increment in an exception safe way the maximum number of tasks
3478  * which the TaskManager object will currently run in its thread pool
3479  * to enable another thread to keep a core active, so that the number
3480  * is automatically decremented again when the
3481  * ThreadManager::IncHandle object has gone out of scope after the
3482  * task has finished making blocking calls or something has thrown.
3483  *
3484  * The documentation on Thread::TaskManager gives an example of its
3485  * use.
3486  *
3487  * This class is available since version 2.2.1 of the library.
3488  */
3490  TaskManager& tm;
3491 public:
3492  /**
3493  * This class cannot be copied. The copy constructor is deleted.
3494  *
3495  * Since 2.0.18/2.2.1
3496  */
3497  IncHandle(const TaskManager::IncHandle&) = delete;
3498 
3499  /**
3500  * This class cannot be copied. The assignment operator is deleted.
3501  *
3502  * Since 2.0.18/2.2.1
3503  */
3505 
3506  /**
3507  * This class requires initialisation with a TaskManager object. The
3508  * default constructor is deleted.
3509  *
3510  * Since 2.0.18/2.2.1
3511  */
3512  IncHandle() = delete;
3513 
3514  /**
3515  * This constructor calls TaskManager::change_max_threads() to
3516  * increment the maximum number of threads a TaskManager object will
3517  * currently run in its thread pool.
3518  * @param tm_ The TaskManager object whose maximum thread limit is to
3519  * be incremented.
3520  * @exception std::bad_alloc If tasks are currently queued for
3521  * execution, a new thread will be started, so this exception may be
3522  * thrown on starting the thread if memory is exhausted and the
3523  * system throws in that case. (On systems with
3524  * over-commit/lazy-commit combined with virtual memory (swap), it is
3525  * rarely useful to check for memory exhaustion).
3526  * @exception Cgu::Thread::TaskError If tasks are currently queued
3527  * for execution, a new thread will be started, so this exception may
3528  * be thrown on starting the thread if it fails to start correctly
3529  * (this would mean that memory is exhausted, the pthread thread
3530  * limit has been reached or pthread has run out of other resources
3531  * to start new threads).
3532  *
3533  * Since 2.0.18/2.2.1
3534  */
3535  explicit IncHandle(TaskManager& tm_): tm(tm_) {
3536  tm_.change_max_threads(1);
3537  }
3538 
3539  /**
3540  * This destructor calls TaskManager::change_max_threads() to
3541  * decrement the maximum number of threads a TaskManager object will
3542  * currently run in its thread pool. It will not throw.
3543  *
3544  * Since 2.0.18/2.2.1
3545  */
3547 };
3548 
3549 } // namespace Thread
3550 
3551 } // namespace Cgu
3552 
3553 #include <c++-gtk-utils/task_manager.tpp>
3554 
3555 #endif
unsigned int get_min_threads() const
StopMode
Definition: task_manager.h:502
unsigned int get_tasks() const
void add_task(const Callback::Callback *task)
Definition: task_manager.h:887
void make_task_packaged_compose(Func &&func, GMainContext *context, When &&when)
Definition: task_manager.h:3355
void make_task_compose(Func &&f, GMainContext *context, std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when)
Definition: task_manager.h:2805
A thread-pool class for managing tasks in multi-threaded programs.
Definition: task_manager.h:500
void make_task_when(When &&when, GMainContext *context, Func &&func)
Definition: task_manager.h:2697
CallbackArg< FreeArgs...> * make_ref(T &t, void(T::*func)(FreeArgs...))
Definition: callback.h:1358
Definition: task_manager.h:63
virtual const char * what() const
Definition: task_manager.h:64
void make_task_when(std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when, GMainContext *context, const T &t, Ret(T::*func)(Params...) const, Args &&...args)
Definition: task_manager.h:1750
This file provides thread-safe asynchronous queue classes.
static void exec(FType &f, const SharedLockPtr< AsyncResult< Ret >> &ret)
Definition: task_manager.h:459
void make_task_when(std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when, GMainContext *context, Ret(*func)(Params...), Args &&...args)
Definition: task_manager.h:2058
void dispatch() const
Definition: task_manager.h:488
This is a smart pointer for managing the lifetime of objects allocated on freestore, with a thread safe reference count.
Definition: shared_ptr.h:644
static void do_fail(const SharedLockPtr< AsyncResult< Ret >> &ret)
Definition: task_manager.h:463
void make_task_compose(Func &&func, GMainContext *context, When &&when)
Definition: task_manager.h:2918
void set_max_threads(unsigned int max)
Cgu::SharedLockPtr< Cgu::AsyncResult< Ret > > make_task_result(T &t, Ret(T::*func)(Params...), Args &&...args)
void set_blocking(bool blocking)
STL namespace.
unsigned int get_idle_time() const
A scoped handle for exception safe incrementing of the maximum number of threads that a TaskManager o...
Definition: task_manager.h:3489
void make_task_when(std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when, GMainContext *context, Func &&f)
Definition: task_manager.h:2586
void make_task_packaged_when(When &&when, Cgu::Releaser *when_releaser, gint priority, GMainContext *context, Func &&func)
This file provides classes for type erasure.
TaskManager & operator=(const TaskManager &)=delete
void add_task(Task &&task, Fail &&fail)
Definition: task_manager.h:1104
FunctorResultExec(FunctorArg &&functor_, const SharedLockPtr< AsyncResult< Ret >> &ret_)
Definition: task_manager.h:492
void make_task_when_full(When &&when, Cgu::Releaser *when_releaser, Fail &&fail, Cgu::Releaser *fail_releaser, gint priority, GMainContext *context, Func &&func)
Definition: task_manager.h:2472
void make_task_when_full(std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when, Cgu::Releaser *when_releaser, std::unique_ptr< const Cgu::Callback::Callback > fail, Cgu::Releaser *fail_releaser, gint priority, GMainContext *context, T &t, Ret(T::*func)(Params...), Args &&...args)
void make_task_when(std::unique_ptr< const Cgu::Callback::CallbackArg< const Ret & >> when, GMainContext *context, T &t, Ret(T::*func)(Params...), Args &&...args)
Definition: task_manager.h:1431
static unsigned int get_max_tasks()
Definition: task_manager.h:691
A thread-safe asynchronous result class.
Definition: async_result.h:165
IncHandle(TaskManager &tm_)
Definition: task_manager.h:3535
void add_task(Task &&task)
Definition: task_manager.h:1019
void set_stop_mode(StopMode mode)
void make_task_packaged_when(When &&when, GMainContext *context, Func &&func)
Definition: task_manager.h:3250
unsigned int get_max_threads() const
unsigned int get_used_threads() const
This file provides a thread-safe signal/slot mechanism, with automatic disconnection.
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Definition: application.h:44
auto make_task_packaged(Func &&f) -> std::future< decltype(f())>
Definition: task_manager.h:3003
StopMode get_stop_mode() const
A scoped locking class for exception safe Mutex locking which tracks the status of its mutex...
Definition: mutex.h:331
This file provides a thread-safe asynchronous result class.
Definition: task_manager.h:502
void change_max_threads(int delta)
void set_idle_time(unsigned int idle)
~IncHandle()
Definition: task_manager.h:3546
TaskManager(const TaskManager &)=delete
CallbackArg Callback
Definition: callback.h:567
Definition: task_manager.h:502
bool get_blocking() const
The callback interface class.
Definition: callback.h:567
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
A class used for tracking EmitterArg and SafeEmitterArg connections.
Definition: emitter.h:352