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