c++-gtk-utils

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

- File List
- File Members

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