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