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