c++-gtk-utils: task_manager.h Source File

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