c++-gtk-utils
|
A class representing a pthread thread which will provide a value. More...
#include <c++-gtk-utils/future.h>
Public Member Functions | |
Future (const Future &) | |
Future & | operator= (const Future &) |
bool | run () |
Val | get () |
bool | cancel () |
Cgu::Callback::SafeFunctor | when (const Cgu::Callback::CallbackArg< const Val & > *cb, gint priority=G_PRIORITY_DEFAULT, GMainContext *context=0) |
Cgu::Callback::SafeFunctor | when (const Cgu::Callback::CallbackArg< const Val & > *cb, Cgu::Releaser &r, gint priority=G_PRIORITY_DEFAULT, GMainContext *context=0) |
void | fail (const Cgu::Callback::Callback *cb, GMainContext *context=0) |
void | fail (const Cgu::Callback::Callback *cb, Cgu::Releaser &r, GMainContext *context=0) |
bool | is_done () const |
bool | is_emitter_done () const |
bool | is_error () const |
bool | is_emitter_error () const |
![]() | |
IntrusiveLockCounter (const IntrusiveLockCounter &) | |
IntrusiveLockCounter & | operator= (const IntrusiveLockCounter &) |
void | ref () |
void | unref () |
IntrusiveLockCounter () | |
virtual | ~IntrusiveLockCounter () |
Static Public Member Functions | |
template<class Ret , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (T &t, Ret(T::*func)()) |
template<class Ret , class Param1 , class Arg1 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (T &t, Ret(T::*func)(Param1), Arg1 &&arg1) |
template<class Ret , class Param1 , class Param2 , class Arg1 , class Arg2 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (T &t, Ret(T::*func)(Param1, Param2), Arg1 &&arg1, Arg2 &&arg2) |
template<class Ret , class Param1 , class Param2 , class Param3 , class Arg1 , class Arg2 , class Arg3 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (T &t, Ret(T::*func)(Param1, Param2, Param3), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class Ret , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (const T &t, Ret(T::*func)() const) |
template<class Ret , class Param1 , class Arg1 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (const T &t, Ret(T::*func)(Param1) const, Arg1 &&arg1) |
template<class Ret , class Param1 , class Param2 , class Arg1 , class Arg2 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (const T &t, Ret(T::*func)(Param1, Param2) const, Arg1 &&arg1, Arg2 &&arg2) |
template<class Ret , class Param1 , class Param2 , class Param3 , class Arg1 , class Arg2 , class Arg3 , class T > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (const T &t, Ret(T::*func)(Param1, Param2, Param3) const, Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class Ret > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (Ret(*func)()) |
template<class Ret , class Param1 , class Arg1 > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (Ret(*func)(Param1), Arg1 &&arg1) |
template<class Ret , class Param1 , class Param2 , class Arg1 , class Arg2 > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (Ret(*func)(Param1, Param2), Arg1 &&arg1, Arg2 &&arg2) |
template<class Ret , class Param1 , class Param2 , class Param3 , class Arg1 , class Arg2 , class Arg3 > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (Ret(*func)(Param1, Param2, Param3), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) |
template<class Ret , class Param1 , class Param2 , class Param3 , class Param4 , class Arg1 , class Arg2 , class Arg3 , class Arg4 > | |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (Ret(*func)(Param1, Param2, Param3, Param4), Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (const std::function< Val(void)> &func) |
static Cgu::IntrusivePtr < Cgu::Thread::Future< Val > > | make (std::function< Val(void)> &&func) |
Public Attributes | |
SafeEmitter | done_emitter |
A class representing a pthread thread which will provide a value.
The Thread::Future class will launch a worker thread, run the function it represents in that thread until it returns, and store the return value so that it can be waited on and/or extracted by another thread. A new Thread::Future object representing the function to be called is created by calling Cgu::Thread::Future<>::make() (a static member function) or from version 2.0.4 the Cgu::Thread::make_future() helper function. The worker thread is then started by calling run(), and the value extracted or waited for by calling get(). The run() method can only be called once, but any number of threads can wait for and/or extract the return value by calling the get() method. The class also provides a SafeEmitter done_emitter public object which emits when the worker thread has finished, and an associated when() function.
The template parameter type of Thread::Future is the type of the return value of the function called by the Thread::Future object. The return value can be any type, including any arbitrarily large tuple or other struct or standard C++ container (but see below about copying).
A Thread::Future object cannot represent a function with a void return type - a compilation error will result if that is attempted. If no return value is wanted, then the Thread::Thread class can be used directly. (However, if in a particular usage this class is thought to be more convenient, the function to be represented by it can be wrapped by another function which provides a dummy return value, such as a dummy int. One possible case for this is where more than one thread wants to wait for the worker thread to terminate, as pthread_join() and so Thread::Thread::join() only give defined behaviour when called by one thread.) In addition, a Thread::Future object cannot represent a function with a non-const reference argument - that would not normally be safe, and a compile error will be generated if that is attempted. However, from version 2.0.0-rc3, const reference arguments can be bound to Thread::Future objects (this is safe, as the Thread::Future object will keep its own copy of the argument passed to it).
The make() method and make_future() functions take a plain function, static member function or non-static member function, which can take up to three arguments in the case of a non-static member function, and four arguments in the case of any other function. In the case of a non-static member function, the referenced object whose member function is to be called must remain in existence until the worker thread has completed. Alternatively, a std::function object can be passed, which can have any number of arguments using std::bind (and which can also bind the referenced object of a non-static member function by taking a copy of it where that is necessary).
Where a std::function object is not passed, internal moving/copying of arguments for the target function to be represented by the Thread::Future object takes place (once by invoking the rvalue move constructor or lvalue copy constructor, as appropriate, when make() or make_future() are called and, if the argument is not a const reference argument, once in the worker thread when run() is called). Therefore, if a non-trivial class object is to be received by the target function as an argument, it is best either (a) if it has a rvalue constructor, to pass it to make() or make_future() as a temporary and have the target function take a const reference argument, or (b) for it to be constructed on free store and for the target function to receive it by pointer, by Cgu::SharedLockPtr, or by a std::shared_ptr implementation which has a thread-safe reference count. Note also that constructing std::function objects using std::bind can cause a number of copies of arguments to be made, so for ordinary usage it is better to pass a function pointer with arguments to make() or make_future() rather than a std::function object.
Copying of the return value of the target function represented by the Thread::Future object also takes place. The run() method will store the return value of that function, so that it is available to the get() method, and therefore copy it once (unless, that is, the target function's return value type has an assignment operator taking an rvalue reference argument). The get() method will indirectly cause it to be copied once more when the copy constructor or assignment operator of the user's object which receives the return value of get() is invoked. Therefore, for return values comprising complex class objects, it is often better if the function represented by the Thread::Future object allocates the return value on free store and returns it by pointer, by Cgu::SharedLockPtr, or by a std::shared_ptr implementation which has a thread-safe reference count. (The example below does not do that however.)
This is a usage example:
If get_primes() were a static member function or plain function, the syntax would be:
The Cgu::Thread::Future::when() functions
From version 2.0.2, the return value of the thread function represented by Cgu::Thread::Future can be obtained asynchronously using Cgu::Thread::Future::when() to execute a function in a glib main loop when the thread function completes. The above example could be reimplemented as:
In this example, the callback which prints the primes to the console would execute in the default program main loop once the thread function providing those primes returns. As an alternative to a free standing print_primes() function, the callback object could be constructed from a C++11 lambda expression using Cgu::Callback::lambda() (available from version 2.0.9).
Lambda functions
As mentioned above, Cgu::Thread::Future objects can be constructed from std::function objects. Because C++11 lambda expressions are implicitly convertible to std::function objects and the only type to be resolved by the Cgu::Thread::Future::make() and Cgu::Thread::make_future() factory functions for such objects is the return type, this means that those functions can be passed a lambda expression, as for example:
However, if make_future() is used, the return type parameter must be explicitly stated:
Lambda expressions which do not capture a variable from their environment are also convertible to a function pointer, but in the absence of an explicit cast the conversion to std::function object will be preferred.
Overloaded functions
Where a member function or ordinary function represented by a Thread::Future object is overloaded, this will cause difficulties in template type deduction when Thread::Future<>::make() or Thread::make_future() are called. With Thread::Future<>::make(), functions may be overloaded on numbers of argument without difficulty, but not with Thread::make_future(). For example:
Neither Thread::Future<>::make() nor Thread::make_future() can be overloaded on types of argument without explicit disambiguation. For example:
Cgu::Thread::Future< Val >::Future | ( | const Future< Val > & | ) |
This class cannot be copied (except by smart pointer). The copy constructor is deleted.
bool Cgu::Thread::Future< Val >::cancel | ( | ) |
Cancels the worker thread in which the function represented by this object runs, if that function has not yet finished. If this method is called and the worker thread is still running and is cancelled in response to a call to this method, then the error flag will be set so that a method calling get() can examine whether the result is valid. If run() has not yet been called or the worker thread has already finished executing the function represented by this object then this function does nothing and returns false. This method is thread safe and may be called by any thread. It will not throw.
void Cgu::Thread::Future< Val >::fail | ( | const Cgu::Callback::Callback * | cb, |
GMainContext * | context = 0 |
||
) |
A utility intended to be used where relevant in conjunction with the when() methods. It enables a callback to be executed in a glib main loop (referred to below as the 'fail' callback) if memory is exhausted and std::bad_alloc was thrown by the thread wrapper of Cgu::Thread::Future after calling run() or by done_emitter when emitting, or if the thread function represented by this Cgu::Thread::Future object threw Cgu::Thread::Exit, exited with an uncaught exception deriving from std::exception or was cancelled, or any callback connected to done_emitter exited with an uncaught exception. It therefore enables errors to be detected and acted on without having a thread wait on the get() method in order to test is_error() or is_emitter_error().
It is implemented by attaching a timeout to the main loop which polls at 100 millisecond intervals and tests is_done()/is_error() and is_emitter_done()/is_emitter_error(). The timeout is automatically removed by the implementation once it has been detected that an error has occurred and the 'fail' callback is executed, or if the thread function represented by this Cgu::Future object and all done_emitter emissions (including execution of any 'when' callback) have completed successfully.
This method can be called before or after the run() method has been called, and whether or not the thread function represented by this Cgu::Thread::Future object has completed.
Once this method has been called, this Cgu::Thread::Future object will always stay in existence until the timeout has been automatically removed by the implementation. Accordingly it is safe to use this method even if the intrusive pointer object returned by the make() methods will go out of scope before the 'fail' callback has executed: the callback will execute correctly irrespective of that.
This method does not have a priority argument: as a polling timeout is created, a particular priority will normally have no significance (in fact, the 'fail' callback will execute in the main loop with a priority of G_PRIORITY_DEFAULT). If in a special case a different polling interval than 100 milliseconds or a different priority is required, users can attach their own polling timeouts to a main loop and carry out the tests by hand.
Four other points should be noted. First, if as well as the when() method being called some other callback has been connected to done_emitter, and that other callback throws, the 'fail' callback will execute. Therefore, if the particular program design requires that the 'fail' callback should only execute if the 'when' callback is not executed (and the 'when' callback only execute if the 'fail' callback does not execute), no other callbacks which throw should be connected to done_emitter.
Secondly, as mentioned in the documentation on the when() method, if the 'when' callback exits with an uncaught exception upon being executed by the main loop or has a non-reference bound argument whose copy constructor throws when it executes, the 'fail' callback will not execute (the exception will have been consumed internally in order to protect the main loop and a g_critical message issued).
Thirdly, avoid if possible having the 'fail' callback represent a function which might throw or which has a non-reference bound argument whose copy constructor might throw (such an exception would be consumed internally in order to protect the main loop and a g_critical message issued, but no other error indication apart from the g_critical message will be provided).
Fourthly, unlike the 'when' callback, a copy of this Cgu::Thread::Future object held by intrusive pointer as returned by the make() methods may safely be bound to the 'fail' callback, which would enable the 'fail' callback to determine whether it is is_error() or is_emitter_error() which returns false.
If glib < 2.32 is used, the glib main loop must have been made thread-safe by a call to g_thread_init() before this function is called. glib >= 2.32 does not require g_thread_init() to be called in order to be thread safe.
cb | The 'fail' callback (the callback to be executed if the thread function represented by this Cgu::Thread::Future object or a done_emitter emission has failed to complete). Ownership is taken of this object, and it will be deleted when it has been finished with. |
context | The glib main context of the thread in whose main loop the 'fail' callback is to be executed (the default of NULL will cause the functor to be executed in the main program loop). |
std::bad_alloc | This method might throw std::bad_alloc if memory is exhausted and the system throws in that case. If it does so, the 'fail' callback will be disposed of. |
Since 2.0.2
void Cgu::Thread::Future< Val >::fail | ( | const Cgu::Callback::Callback * | cb, |
Cgu::Releaser & | r, | ||
GMainContext * | context = 0 |
||
) |
This is a version of the fail() utility for use in conjunction with the when() methods, which takes a Releaser object for automatic disconnection of the callback functor passed as an argument to this method if the object having the callback function as a member is destroyed.
This method enables a callback to be executed in a glib main loop if memory is exhausted and std::bad_alloc was thrown by the thread wrapper of Cgu::Thread::Future after calling run() or by done_emitter when emitting, or if the thread function represented by this Cgu::Thread::Future object threw Cgu::Thread::Exit, exited with an uncaught exception deriving from std::exception or was cancelled, or any callback connected to done_emitter exited with an uncaught exception. It therefore enables errors to be detected and acted on without having a thread wait on the get() method in order to test is_error() or is_emitter_error().
This method can be called before or after the run() method has been called, and whether or not the thread function represented by this Cgu::Thread::Future object has completed.
The documentation for the version of this method which does not take a Releaser object gives further details of how this method is used.
If glib < 2.32 is used, the glib main loop must have been made thread-safe by a call to g_thread_init() before this function is called. glib >= 2.32 does not require g_thread_init() to be called in order to be thread safe.
cb | The 'fail' callback (the callback to be executed if the thread function represented by this Cgu::Thread::Future object or a done_emitter emission has failed to complete). Ownership is taken of this object, and it will be deleted when it has been finished with. |
r | A Releaser object for automatic disconnection of the 'fail' callback if the object of which the callback function is a member is destroyed. |
context | The glib main context of the thread in whose main loop the 'fail' callback is to be executed (the default of NULL will cause the functor to be executed in the main program loop). |
std::bad_alloc | This method might throw std::bad_alloc if memory is exhausted and the system throws in that case. If it does so, the 'fail' callback will be disposed of. |
Cgu::Thread::MutexError | This method will throw Cgu:Thread::MutexError if initialisation of the mutex in a SafeEmitterArg object constructed by Cgu::start_timeout() fails. If it does so, the 'fail' callback will be disposed of. (It is often not worth checking for this, as it means either memory is exhausted or pthread has run out of other resources to create new mutexes.) |
Since 2.0.2
Val Cgu::Thread::Future< Val >::get | ( | ) |
Gets the value obtained from the function which is represented by this object. If the worker thread launched by the call to run() has not completed, then this method will block until it has completed. If run() has not been called, then run() will be called (and this method will block until the launched worker thread completes). If the function which is represented by this object throws Cgu::Thread::Exit or an uncaught exception derived from std::exception, then the exception will have been consumed by this Cgu::Thread::Future object and the error flag will have been set. The error flag will also have been set if the worker thread is cancelled or the thread wrapper in this Cgu::Thread::Future object threw std::bad_alloc. This method is thread safe and may be called by any thread (and by more than one thread). It is also strongly exception safe: no data will be lost if extracting the value fails.
Cgu::Thread::FutureThreadError | This method might throw Cgu::Thread::FutureThreadError if run() has not previously been called and the thread did not start properly when this function called run(). |
std::bad_alloc | This method might throw std::bad_alloc if run() has not previously been called, memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) |
bool Cgu::Thread::Future< Val >::is_done | ( | ) | const |
bool Cgu::Thread::Future< Val >::is_emitter_done | ( | ) | const |
Since 2.0.2
bool Cgu::Thread::Future< Val >::is_emitter_error | ( | ) | const |
bool Cgu::Thread::Future< Val >::is_error | ( | ) | const |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of the bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of the bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of the bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
|
static |
Constructs a new Cgu::Thread::Future object (returned by Cgu::IntrusivePtr<Cgu::Thread::Future<Val>>). The type parameter Val represents the return value of the function to be represented by the new object. From version 2.0.4, it will usually be more convenient to call the Cgu::Thread::make_future() function, which is a convenience wrapper for this static method.
std::bad_alloc | It might throw std::bad_alloc if memory is exhausted and the system throws in that case. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) It will also throw if the copy constructor or assignment operator of a bound argument throws, or the default constructor of the return value type throws. |
Future& Cgu::Thread::Future< Val >::operator= | ( | const Future< Val > & | ) |
This class cannot be copied (except by smart pointer). The assignment operator is deleted.
bool Cgu::Thread::Future< Val >::run | ( | ) |
Runs the function represented by this Cgu::Thread::Future object in a new worker thread. That function will only be run once. If this is the first time this method has been called, it will start the worker thread and return true, and if it has previously been called, this method will do nothing and return false. This method is thread safe and may be called by a different thread from the one which called make().
Cgu::Thread::FutureThreadError | This method might throw Cgu::Thread::FutureThreadError if it has not previously been called and the thread did not start properly. If it does throw, this Cgu::Thread::Future object is defunct and further attempts to call this method will return immediately with a false value. (It is often not worth checking for this exception, as it means either memory is exhausted, the pthread thread limit has been reached or pthread has run out of other resources to start new threads.) |
std::bad_alloc | This method might throw std::bad_alloc if it has not previously been called, and memory is exhausted and the system throws in that case. If it does throw, this Cgu::Thread::Future object is defunct and further attempts to call this method will return immediately with a false value. (This exception will not be thrown if the library has been installed using the –with-glib-memory-slices-no-compat configuration option: instead glib will terminate the program if it is unable to obtain memory from the operating system.) |
Cgu::Callback::SafeFunctor Cgu::Thread::Future< Val >::when | ( | const Cgu::Callback::CallbackArg< const Val & > * | cb, |
gint | priority = G_PRIORITY_DEFAULT , |
||
GMainContext * | context = 0 |
||
) |
A utility enabling the value returned by the thread function represented by this Cgu::Thread::Future object to be dealt with asynchronously rather than by (or in addition to) a call to the get() method. It causes the callback passed as an argument to this method (referred to below as the 'when' callback) to be executed by a thread's main loop if and when the thread function represented by this Cgu::Thread::Future object finishes correctly - the 'when' callback is passed that thread function's return value when it is invoked. This method is thread safe, and may be called by any thread.
This functionality is implemented by connecting an internal dispatching callback to the done_emitter object.
The 'when' callback should take a single unbound argument comprising a const reference to the return type of the thread function represented by this Cgu::Thread::Future object. (So, in the case of a Future<int> object, the callback function should take a const int& argument as the unbound argument.) The 'when' callback can have any number of bound arguments, except that a bound argument may not include a copy of this Cgu::Thread::Future object held by intrusive pointer as returned by the make() methods (that would result in this Cgu::Thread::Future object owning, via done_emitter, a reference to itself and so become incapable of being freed). The 'when' callback may, however, take a pointer to this Cgu::Thread::Future object, as obtained by the Cgu::IntrusivePtr::get() method, because this Cgu::Thread::Future object is guaranteed to remain in existence until the callback has completed executing.
This method cannot be called after the thread function represented by this Cgu::Thread::Future object has completed (either successfully or unsuccessfully) so that is_done() would return true, and if this is attempted a Cgu::Thread::FutureWhenError exception will be thrown. Therefore, generally this method should be called before the run() method has been called.
Once the run() method has been called, this Cgu::Thread::Future object will always stay in existence until the thread function represented by it has completed (whether correctly, by cancellation or by a thrown exception), and any 'when' callback (and any other callbacks connected to the done_emitter object) and any 'fail' callback have completed. Accordingly it is safe to use this method even if the intrusive pointer object returned by the make() methods will go out of scope before the 'when' callback has executed: the callback will execute correctly irrespective of that.
Summary: use of this method is safe and has been implemented in a way which does not give rise to timing issues.
If memory is exhausted and std::bad_alloc is thrown by the thread wrapper of Cgu::Thread::Future after run() is called or by done_emitter when emitting, or if the thread function represented by this Cgu::Thread::Future object throws Cgu::Thread::Exit, exits with an uncaught exception deriving from std::exception or is cancelled, or if the copy constructor of a non-reference bound argument of the 'when' callback throws, or any other callback has been connected to done_emitter before this method is called which exits with an uncaught exception, then the 'when' callback will not execute (instead the exception concerned will be consumed and an error indicated). With many systems, swap memory combined with memory over-commit makes it pointless to check for std::bad_alloc (and even more so in programs using glib, as glib aborts a program where it cannot obtain memory from the operating system). So subject to that, if the user program is designed so that the thread function represented by this Cgu::Thread::Future object does not exit with uncaught exceptions, does not throw Cgu::Thread::Exit and is not cancelled, and so that the 'when' callback does not exit with an uncaught exception and either has no non-reference bound arguments or the copy constructors of any non-reference bound arguments do not throw, and if this method is called before any other callbacks are connected to done_emitter, the possibility of failure can be disregarded.
In cases where that is not true and detecting whether a failure has occurred is required, a fail() method is provided. It should be noted that a callback handed to the fail() method will not execute in a case of error if the error comprises the 'when' callback exiting with an uncaught exception when it is executed by the main loop, or the copy constructor of one of its non-reference bound arguments throwing when it executes (such an exception would be consumed internally in order to protect the main loop and a g_critical message issued). If the 'when' callback might exit with an uncaught exception when executing or have the copy constructor of a non-reference bound argument throw, and doing something other than consuming the exception and issuing a g_critical message is required, then a different approach is to start a new thread to wait on the get() method which can act on the result of is_error() directly.
If glib < 2.32 is used, the glib main loop must have been made thread-safe by a call to g_thread_init() before this function is called. glib >= 2.32 does not require g_thread_init() to be called in order to be thread safe.
cb | The 'when' callback (the callback to be executed when the function represented by this Cgu::Thread::Future object has successfully completed). Ownership is taken of this object, and it will be deleted when it has been finished with. |
priority | The priority to be given to the 'when' callback in the main loop after the thread function represented by this Cgu::Thread::Future object has successfully completed. In ascending order of priorities, priorities are G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is G_PRIORITY_DEFAULT. This determines the order in which the callback will appear in the event list in the main loop, not the priority which the OS will adopt. |
context | The glib main context of the thread in whose main loop the 'when' callback is to be executed (the default of NULL will cause the callback to be executed in the main program loop). |
Cgu::Thread::FutureWhenError | This method will throw Cgu::Thread::FutureWhenError if it is called after the thread function represented by this Cgu::Thread::Future object has completed. If it does so, the 'when' callback will be disposed of. |
std::bad_alloc | This method might throw std::bad_alloc if memory is exhausted and the system throws in that case. If it does so, the 'when' callback will be disposed of. |
Since 2.0.2
Cgu::Callback::SafeFunctor Cgu::Thread::Future< Val >::when | ( | const Cgu::Callback::CallbackArg< const Val & > * | cb, |
Cgu::Releaser & | r, | ||
gint | priority = G_PRIORITY_DEFAULT , |
||
GMainContext * | context = 0 |
||
) |
This is a version of the utility enabling the value returned by the thread function represented by this Cgu::Thread::Future object to be dealt with asynchronously, which takes a Releaser object for automatic disconnection of the callback passed as an argument to this method (referred to below as the 'when' callback), if the object having the 'when' callback function as a member is destroyed. For this to be race free, the lifetime of that object must be controlled by the thread in whose main loop the 'when' callback will execute.
If the 'when' callback has not been released, this method causes it to be executed by a thread's main loop if and when the thread function represented by this Cgu::Thread::Future object finishes correctly - the 'when' callback is passed that thread function's return value when it is invoked. This method is thread safe, and may be called by any thread.
This functionality is implemented by connecting an internal dispatching callback to the done_emitter object.
The 'when' callback should take a single unbound argument comprising a const reference to the return type of the thread function represented by this Cgu::Thread::Future object. (So, in the case of a Future<int> object, the callback function should take a const int& argument as the unbound argument.) The 'when' callback can have any number of bound arguments, except that a bound argument may not include a copy of this Cgu::Thread::Future object held by intrusive pointer as returned by the make() methods (that would result in this Cgu::Thread::Future object owning, via done_emitter, a reference to itself and so become incapable of being freed). The 'when' callback may, however, take a pointer to this Cgu::Thread::Future object, as obtained by the Cgu::IntrusivePtr::get() method, because this Cgu::Thread::Future object is guaranteed to remain in existence until the callback has completed executing.
This method cannot be called after the thread function represented by this Cgu::Thread::Future object has completed (either successfully or unsuccessfully) so that is_done() would return true, and if this is attempted a Cgu::Thread::FutureWhenError exception will be thrown. Therefore, generally this method should be called before the run() method has been called.
The documentation for the version of this method which does not take a Releaser object gives further details of how this method is used.
If glib < 2.32 is used, the glib main loop must have been made thread-safe by a call to g_thread_init() before this function is called. glib >= 2.32 does not require g_thread_init() to be called in order to be thread safe.
cb | The 'when' callback (the callback to be executed when the function represented by this Cgu::Thread::Future object has successfully completed). Ownership is taken of this object, and it will be deleted when it has been finished with. |
r | A Releaser object for automatic disconnection of the 'when' callback if the object of which the callback function is a member is destroyed. |
priority | The priority to be given to the 'when' callback in the main loop after the thread function represented by this Cgu::Thread::Future object has successfully completed. In ascending order of priorities, priorities are G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE, G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is G_PRIORITY_DEFAULT. This determines the order in which the callback will appear in the event list in the main loop, not the priority which the OS will adopt. |
context | The glib main context of the thread in whose main loop the 'when' callback is to be executed (the default of NULL will cause the callback to be executed in the main program loop). |
Cgu::Thread::FutureWhenError | This method will throw Cgu::Thread::FutureWhenError if it is called after the thread function represented by this Cgu::Thread::Future object has completed. If it does so, the 'when' callback will be disposed of. |
std::bad_alloc | This method might throw std::bad_alloc if memory is exhausted and the system throws in that case. If it does so, the 'when' callback will be disposed of. |
Cgu::Thread::MutexError | This method will throw Cgu:Thread::MutexError if initialisation of the mutex in a SafeEmitterArg object constructed by this method fails. If it does so, the 'when' callback will be disposed of. (It is often not worth checking for this, as it means either memory is exhausted or pthread has run out of other resources to create new mutexes.) |
Since 2.0.2
SafeEmitter Cgu::Thread::Future< Val >::done_emitter |
A Cgu::SafeEmitter object which is emitted when the function represented by this Cgu::Thread::Future object finishes correctly (that is, the function is not cancelled and does not throw any uncaught exceptions). By itself it does not do too much as it is emitted (and connected callbacks execute in) the same worker thread immediately after the Future function has completed. However, any thread can connect a Callback object to this Cgu::SafeEmitter object and a connected callback can, say, cause another Callback to be executed in a thread's main loop using Cgu::Callback::post(), and from version 2.0.2 when() methods are provided which will do this for users automatically. Once the run() method has been called, this Cgu::Thread::Future object (and so done_emitter) will always stay in existence until the function represented by it has completed (whether correctly, by cancellation or by a thrown exception) and any callbacks connected to the done_emitter object have completed, irrespective of whether the intrusive pointer returned by the make() methods has gone out of scope.