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