c++-gtk-utils

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

- File List
- File Members

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