callback.h
Go to the documentation of this file.
/* Copyright (C) 2008 to 2013 Chris Vine
The library comprised in this file or of which this file is part is
distributed by Chris Vine under the GNU Lesser General Public
License as follows:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License, version 2.1, for more details.
You should have received a copy of the GNU Lesser General Public
License, version 2.1, along with this library (see the file LGPL.TXT
which came with this source code package in the c++-gtk-utils
sub-directory); if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
However, it is not intended that the object code of a program whose
source code instantiates a template from this file or uses macros or
inline functions (of any length) should by reason only of that
instantiation or use be subject to the restrictions of use in the GNU
Lesser General Public License. With that in mind, the words "and
macros, inline functions and instantiations of templates (of any
length)" shall be treated as substituted for the words "and small
macros and small inline functions (ten lines or less in length)" in
the fourth paragraph of section 5 of that licence. This does not
affect any other reason why object code may be subject to the
restrictions in that licence (nor for the avoidance of doubt does it
affect the application of section 2 of that licence to modifications
of the source code in this file).
*/
#ifndef CGU_CALLBACK_H
#define CGU_CALLBACK_H
/**
* @file callback.h
* @brief This file provides classes encapsulating callbacks.
*
* \#include <c++-gtk-utils/callback.h>
*
* These classes encapsulate callbacks (they are closures). They
* comprise a generic callback creation and execution interface.
* There is a basic Callback::Callback type, which is an entire
* closure or 'thunk', where all the arguments are bound in the
* constructor and is completely opaque. Callback::CallbackArg<T...>
* is a class which takes unbound arguments of the template types when
* the callback is dispatched, with any other arguments being bound at
* construction time. (The opaque Callback::Callback type is in fact
* just a typedef for Callback::CallbackArg<>: the two types are
* interchangeable.)
*
* The classes can represent static and non-static member functions
* and plain functions. In the case of a non-static member function,
* the object whose member function the callback represents must
* remain in existence until any invocations of the callback have
* completed. The function referred to must be one of void return
* type. A callback object can also be constructed from any function
* object, provided that it is of void return type (which would
* amongst other things enable, where necessary, the binding of the
* referenced object of a non-static member function by taking an
* internal copy of it using std::bind or by lambda capture).
*
* They are particularly useful where a callback object may need to be
* handed between threads.
*
* The classes can also be useful for general event passing when used
* together with the Callback::post() functions, or as the data
* argument of a call to g_signal_connect_data() in a case where a
* better design arises when passing arguments known at connect time
* by storing them in the callback object itself, or as the
* continuation for GIO async operations.
*
* These classes are also used in the Emitter/EmitterArg classes in
* emitter.h, which enable callbacks to be connected to an emitter and
* provide for automatic disconnection where a class object whose
* member a callback represents ceases to exist.
*
* The Callback::make() functions
* ------------------------------
*
* The templated helper Callback::make() functions make it trivial to
* create a callback object of the correct type. The ordinary
* Callback::make() functions (that is, those not taking a
* std::function object) provide for a maximum of five bound arguments
* to pass to the relevant function or class method, and an unlimited
* number of unbound arguments, but unbound arguments must be the last
* (trailing) arguments of the relevant function or method to be
* called if there is a bound argument. Callback/CallbackArg classes
* do not provide for a return value. If a result is wanted, users
* should pass an unbound argument by reference or pointer (or pointer
* to pointer).
*
* Although as mentioned above only five bound arguments are provided
* for by callbacks constructed by the ordinary Callback::make()
* functions, as any of those arguments can be a struct, any number of
* arguments can be passed as members of a struct or a std::tuple. In
* addition, a callback object can be constructed using
* Callback::make() from a std::function object, which can have any
* number of arguments bound to it, and in any order (that is, unbound
* arguments may precede bound arguments).
*
* The Callback::make() functions not taking a std::function object do
* a direct type mapping from the bound arguments of the function or
* method represented by the callback object to the arguments stored
* by the callback object. Bound value arguments of the relevant
* function or method to be called are therefore stored by value in
* the callback object. A bound argument can comprise a reference
* argument (T& or const T&) if the template parameters of the
* Callback::make() call are qualified by hand to avoid a type
* mismatch: see under "Usage" below for further particulars, and if
* the reference argument is non-const this allows the referenced
* argument to be mutated. However as this would result in the
* lifetime of the argument not being controlled by the callback
* object (it would not keep its own copy), it will often be unsafe to
* do so. (The documentation on Thread::JoinableHandle gives a usage
* where where binding a reference argument would be safe.)
*
* From version 2.0.0-rc3, the library also provides
* Callback::make_ref() functions, which force the callback object to
* keep a copy of the value passed where a target function argument is
* a const reference. It is therefore safe with const reference
* arguments. No explicit type qualification is required by
* Callback::make_ref(). In addition the Callback::make_ref()
* functions provide for more efficient passing of class type bound
* arguments (by l-value or r-value reference) than does
* Callback::make(): see further below.
*
* The Callback::make_ref() functions
* ----------------------------------
*
* In order to enable the widest variety of types to be accepted as
* arguments (including reference arguments in those cases where it is
* safe, and also string literals), as mentioned above when
* constructing a callback object from other than a std::function
* object, Callback::make() receives non-reference bound arguments by
* value, and if unoptimised these may be copied up to two times, and
* once more when the target function is dispatched. Where a bound
* argument is a pointer or a fundamental type (an integral or
* floating-point type), optimization by copy elision will reduce the
* number of times argument copying takes place when constructing a
* callback object to once, but the standard does not permit that with
* class types where the constructor or destructor have side effects
* or it cannot be ascertained whether they have side effects.
*
* Therefore, to cater for cases where a target function takes a class
* type argument by const reference or value, from version 2.0.0-rc3
* the Callback::make_ref() functions are provided. Unlike
* Callback::make(), when constructing a callback for a target
* function taking a const reference bound argument,
* Callback::make_ref() will force the callback object to keep a copy
* of the argument instead of a reference to that argument. This
* makes the use of const reference arguments safe (at the cost of the
* storing of that copy). It cannot be used with non-const
* references. In addition Callback::make_ref() automatically chooses
* the most efficient means of passing class type arguments for
* storage by the callback object, that is by l-value reference or
* r-value reference, as appropriate.
*
* In the case of a value argument, at callback dispatch time one
* additional copy will be made in the normal way when the target
* function is called, but in the case of a const reference argument
* no such additional copy will be made. What all this means is that,
* where bound arguments include a non-trivial class type, the most
* efficient and exception safe strategy is usually:
*
* 1. If that class type has a rvalue constructor, to have the target
* function take that type by const reference argument, and pass a
* newly constructed object of that type to Callback::make_ref() as a
* temporary (so that it is passed by r-value reference and stored in
* the callback object without any copying at all), or
* 2. To construct the object of the class type on free store and held
* by Cgu::SharedPtr, Cgu::SharedLockPtr or std::shared_ptr, have the
* target function take it by const Cgu::SharedPtr&, const
* Cgu::SharedLockPtr& or const std::shared_ptr&, and construct the
* callback object using Callback::make_ref().
*
* This flexibility of Callback::make_ref() has a downside: unlike
* Callback::make(), Callback::make_ref() cannot resolve overloaded
* functions by argument type. Where a function has two or more
* overloads taking the same number of arguments, explicit
* disambiguation by the user is required (see further below under
* Overloaded Functions).
*
* Summary: If a callback object's bound arguments are all simple
* fundamental types such as pointers (including C strings), integers
* or floating points, use Callback::make(). Where bound arguments
* include class types, use Callback::make_ref().
*
* The Callback::make_val() functions
* ----------------------------------
*
* The library also provides Callback::make_val() functions. These
* are provided to retain code compatibility with version 1.2 of the
* library. They were optimised for use where a target function takes
* bound arguments of class type by value, but are now deprecated and
* superseded by the automatic variable type mapping of
* Callback::make_ref(). Callback::make_ref() should now be used
* instead of Callback::make_val().
*
* Constructing callbacks from std::function objects
* -------------------------------------------------
*
* The Callback::make() factory functions can also construct a
* callback object from a std::function object, which would enable a
* callback to take more than 5 bound arguments, or to have a bound
* argument which is passed after (or mixed with) unbound arguments,
* or to have its own copy of the referenced object of a non-static
* member function bound to it.
*
* However, the genericity of the binding of arguments implemented in
* std::function and std::bind comes at a cost. Arguments bound to a
* std::function object can be copied a significant number of times
* (libstdc++ for example can copy class types four times when
* constructing a std::function object and two more times when
* executing the function, unless they have a r-value constructor, in
* which case they are copied twice and once respectively with two and
* one additional calls to the r-value constructor). Non-trivial
* class types should therefore only be passed as bound arguments to
* std::function objects by pointer or smart pointer.
*
* Note that the overload of Callback::make() for std::function
* objects has a version taking a r-value reference for the lossless
* passing through of temporaries to the callback object, and a
* version taking a const reference for std::function objects which
* are l-values. For std::function objects, Callback::make() and
* Callback::make_ref() are all synonyms (the way arguments are dealt
* with for std::function objects is determined by std::bind() and
* std::ref()).
*
* From version 2.0.9, in many uses it is better to pass a function
* object (such as the return value of std::bind(), or one generated
* by a lambda expression) to Callback::lambda(), which takes any
* arbitrary callable object directly as a template parameter.
*
* The Callback::lambda() functions
* --------------------------------
*
* Callback objects for C++11 lambda expressions can be constructed
* using Callback::make() by passing the lambda object via a temporary
* std::function object (see under Usage below for an example).
* However, from version 2.0.9 the Callback::lambda() factory function
* is provided enabling callbacks for C++11 lambda expressions to be
* constructed more directly. This is nice, as by using
* Callback::lambda() a callback can, for example, be executed by a
* glib main loop using Callback::post() with:
* @code
* using namespace Cgu;
* post(Callback::lambda<>([]() {std::cout << "Hello glib\n";})); // post() found by argument dependent lookup
* @endcode
* Further examples are given under Usage below.
*
* Callback::lambda() can construct a callback object from any
* arbitrary function object, such as the return value of std::bind().
* Using Callback::lambda() to construct such a callback object,
* rather than using Callback::make() with a temporary std::function
* object, will also be more efficient, as when executed it would
* normally avoid the additional virtual function call that would
* arise with std::function.
*
* When using Callback::lambda(), the unbound argument types must be
* specified explicitly (they cannot be deduced from the lambda
* expression).
*
* From version 2.0.10, Callback::lambda() can be called for lambda
* expressions which are declared mutable capturing bound arguments by
* value (in version 2.0.9, the function could only be called for
* non-mutable lambda expressions). From version 2.0.16, it can be
* passed callable objects which are lvalues as well as rvalues (prior
* to version 2.0.16, it could only be passed callable objects which
* are rvalues).
*
* One other feature of Callback::lambda() is that the callable object
* passed to it need not be of void return type. However, if the
* callable object does return a value, that value is discarded. If a
* result is wanted, an unbound reference or pointer argument should
* be passed when the callback is executed, to which the result can be
* assigned.
*
* If using lambda expressions with gcc, gcc-4.5 or greater is needed.
* The header file callback.h can be included without error with
* gcc-4.4, but callable objects cannot be constructed using C++11
* lambda syntax.
*
* Functors
* --------
*
* If a functor class of void return type is required (say for passing
* to a c++ algorithm or container, or for automatic lifetime
* management of the Callback object), the Callback::Functor and
* Callback::FunctorArg wrapper classes can be used. However, for
* many c++ algorithms where anonymous functors created as temporaries
* can be used, the std::ptr_fun(), std::mem_fn() and std::bind()
* factory functions or a lambda expression will be a more obvious
* choice. Callback::Functor and Callback::FunctorArg are to be
* preferred to std::function where value arguments are to be bound
* (see above), unless something other than a void return type is
* required.
*
* Callback::SafeFunctor and Callback::SafeFunctorArg classes are the
* same as Callback::Functor and Callback::FunctorArg classes, except
* that objects of the safe version may be passed and copied between
* threads and put in different containers in different threads (that
* is, the reference count maintained with respect to the contained
* callback object is thread-safe). They use a SharedLockPtr object
* to hold the referenced callback object.
*
* Memory allocation
* -----------------
*
* If the library is installed using the
* \--with-glib-memory-slices-compat or
* \--with-glib-memory-slices-no-compat configuration options, any
* Callback::Functor, Callback::FunctorArg, Callback::SafeFunctor or
* Callback::SafeFunctorArg objects constructed on free store (usually
* they won't be) will be constructed in glib memory slices. A
* contained Callback::Callback or Callback::CallbackArg object, which
* will always be constructed on free store, will be constructed in
* glib memory slices if the \--with-glib-memory-slices-no-compat
* configuration option is chosen.
*
* Usage
* -----
*
* For a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, int, const char*), usage for a fully bound
* callback or functor would be:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::Callback* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n");
* cb->dispatch();
* delete cb;
*
* Callback::Functor f{Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n")};
* f();
* @endcode
*
* Or for a partially bound callback or functor:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::CallbackArg<int, const char*>* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1);
* cb->dispatch(arg2, "Hello\n");
* delete cb;
*
* Callback::FunctorArg<int, const char*> f{Callback::make(my_obj, &MyClass::my_method, arg1)};
* f(arg2, "Hello\n");
* @endcode
*
* The syntax for the construction of a callback object representing a
* static member function with a signature void MyClass::my_func(int,
* const char*), or for a normal function, is similar to the
* non-static member function case, except that the call to
* Callback::make would comprise:
*
* @code
* Callback::make(&MyClass::my_func, arg1, arg2, "Hello\n");
* @endcode
* (fully bound), or
* @code
* Callback::make(&MyClass::my_func, arg1);
* @endcode
* (partially bound), and so on.
*
* To bind to reference arguments, the call to Callback::make() must
* be explicitly typed. For a class object my_obj of type MyClass,
* with a method void MyClass::my_method(int&), usage for a fully
* bound callback or functor would be:
*
* @code
* int arg = 1;
* Callback::Callback* cb =
* Callback::make<MyClass, int&>(my_obj, &MyClass::my_method, arg);
* @endcode
*
* Note however the caveats above about binding to reference
* arguments.
*
* No similar explicit typing is required by Callback::make_ref().
* Thus for a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, const Something&), usage for a fully bound
* callback or functor would be:
*
* @code
* int arg1 = 1;
* Something arg2;
* Callback::Callback* cb =
* Callback::make_ref(my_obj, &MyClass::my_method, arg1, arg2);
* @endcode
*
* From version 2.0.9, Callback::lambda() provides an easy
* way of dealing with lambda expressions, for example:
*
* @code
* Callback::Callback* cb;
* {
* std::string s("Hello");
* cb = Callback::lambda<>([=](){std::cout << s << std::endl;});
* }
* cb->dispatch(); // 's' is now out of scope, but it has been captured by value
* // by the lambda object and is now held by the callback object
* delete cb;
* @endcode
*
* With Callback::lambda(), the types of the unbound arguments must be
* explicitly specified as they cannot be deduced. Unbound arguments
* can comprise reference arguments. For example:
*
* @code
* int res;
* auto cb = Callback::lambda<int, int, int&>([](int j, int k, int& r) {r = j * k;});
* cb->dispatch(2, 3, res);
* std::cout << res << std::endl;
* delete cb;
* @endcode
*
* Callback::lambda() can take any function object, such as one
* returned by std::bind(). So, constructing a callback object
* representing a class object my_obj of type MyClass, with a method
* void MyClass::my_method(int, int, int, double, const char*), where
* a value is to be bound to the second argument could comprise:
*
* @code
* using namespace std::placeholders; // for _1, _2, _3 and _4
* int arg = 1;
* auto cb = Callback::lambda<int, int, double, const char*>(
* std::bind(&MyClass::my_method, &my_obj,
* _1, arg, _2, _3, _4)
* );
* cb->dispatch(5, 3, 10.2, "Hello\n");
* delete cb;
* @endcode
*
* Using std::bind, if the bound argument were a reference (that is,
* the signature of MyClass::my_method were (int, int&, int, double,
* const char*) and it were safe to do so (see above), it could be
* bound with std::ref(), as in:
*
* @code
* using namespace std::placeholders; // for _1, _2, _3 and _4
* int arg;
* auto cb = Callback::lambda<int, int, double, const char*>(
* std::bind(&MyClass::my_method, &my_obj,
* _1, std::ref(arg), _2, _3, _4)
* );
* @endcode
*
* Prior version to 2.0.9, lambda expressions and the return value of
* std::bind() would have to be passed by using a temporary
* std::function object and Callback::make, as follows:
*
* @code
* Callback::Callback* cb;
* {
* std::string s("Hello");
* cb = Callback::make(std::function<void()>{[=](){std::cout << s << std::endl;}});
* }
* cb->dispatch();
* delete cb;
* @endcode
*
* Overloaded functions
* --------------------
*
* Note that creating callbacks for overloaded functions can give rise
* to an ambiguity when using Callback::make(), arising from the fact
* that the callback object may have an unbound argument. For
* example:
*
* @code
* class MyClass {
* ...
* void add(int i);
* void add(int i, int j);
* void add(double d);
* };
* MyClass obj;
* using namespace Cgu;
* Callback::Callback* cb1 = Callback::make(obj, &MyClass::add, 1, 2); // ok
* Callback::Callback* cb2 = Callback::make(obj, &MyClass::add, 1.0); // ok
* Callback::Callback* cb3 = Callback::make(obj, &MyClass::add, 1); // ambiguous - compilation failure
* @endcode
*
* The third call to Callback::make() is ambiguous, as it could be
* creating a callback for either the function MyClass::add(int) with
* no unbound argument (that is, creating a Callback::Callback
* object), or the function MyClass::add(int, int) with an unbound int
* argument (that is, creating a Callback::CallbackArg<int> object).
* This situation could be disambiguated by specifically stating the
* type of the function which is to be chosen, namely, to instantiate
* the callback in the third call with:
*
* @code
* // either:
* Callback::Callback* cb3 =
* Callback::make(obj, static_cast<void (MyClass::*)(int)>(&MyClass::add), 1);
* // or:
* Callback::CallbackArg<int>* cb3 =
* Callback::make(obj, static_cast<void (MyClass::*)(int, int)>(&MyClass::add), 1);
* @endcode
*
* Callback::make_ref() is less capable than Callback::make() at
* deducing template types. It cannot resolve overloaded functions by
* examining the arguments passed to it. For example, take a class
* MyClass as follows:
*
* @code
* class MyClass {
* ...
* void add(int i, const double& d);
* void add(const int& j, const int& k);
* };
* @endcode
*
* Callback::make_ref() would require explicit disambiguation like
* this:
*
* @code
* Callback::Callback* cb1 =
* Callback::make_ref(obj, static_cast<void (MyClass::*)(int, const double&)>(&MyClass::add), 1, 2.2);
* Callback::Callback* cb2 =
* Callback::make_ref(obj, static_cast<void (MyClass::*)(const int&, const int&)>(&MyClass::add), 4, 5);
* @endcode
*
* Note also that, for CallbackArg objects created from std::function
* objects, the std::function constructors and the std::mem_fn() and
* std::bind() functions normally do not allow any function
* overloading without explicit disambiguation.
*
* Posting of callbacks
* --------------------
*
* This file also provides Callback::post() functions which will
* execute a callback in a glib main loop and can be used (amongst
* other things) to pass an event from a worker thread to the main
* program thread. In that respect, it provides an alternative to the
* Notifier class. It is passed a pointer to a Callback::Callback
* object created with a call to Callback::make() or
* Callback::lambda().
*
* To provide for thread-safe automatic disconnection of the callback
* if the object whose method it represents is destroyed before the
* callback executes in the main loop, include a Releaser as a public
* member of that object and pass the Releaser object as the second
* argument of Callback::post(). Note that for this to be race free,
* the lifetime of the remote object whose method is to be invoked
* must be determined by the thread to whose main loop the callback
* has been attached. When the main loop begins invoking the
* execution of the callback, the remote object must either wholly
* exist (in which case the callback will be invoked) or have been
* destroyed (in which case the callback will be ignored), and not be
* in some transient half-state governed by another thread.
*
* Advantages as against Notifier:
*
* 1. If there are a lot of different events requiring callbacks to be
* dispatched in the program from worker threads to the main
* thread, this avoids having separate Notifier objects for each
* event.
* 2. It is easier to pass arguments with varying values - they can be
* passed as arguments to the Callback::make functions and no
* special synchronisation is normally required (the call to
* g_source_attach() invokes locking of the main loop which will
* have the effect of ensuring memory visibility). With a Notifier
* object it may be necessary to use an asynchronous queue to pass
* variable values (or to bind a reference to the data, thus
* normally requiring separate synchronisation).
* 3. Although the callback would normally be sent for execution by
* the main program loop, and that is the default, it can be sent
* for execution by any thread which has its own
* GMainContext/GMainLoop objects. Thus callbacks can be passed
* for execution between worker threads, or from the main program
* thread to worker threads, as well as from worker threads to the
* main program thread.
*
* Disadvantages as against Notifier:
*
* 1. Less efficient, as a new callback object has to be created on
* freestore every time the callback is invoked, together with a
* new Emitter object if a Releaser is used to track the callback.
* 2. Multiple callbacks relevant to a single event cannot be invoked
* from a single call for the event - each callback has to be
* separately dispatched.
*/
/**
* @namespace Cgu::Callback
* @brief This namespace provides classes encapsulating callbacks.
*
* \#include <c++-gtk-utils/callback.h>
*
* These classes encapsulate callbacks (they are closures). They
* comprise a generic callback creation and execution interface.
* There is a basic Callback::Callback type, which is an entire
* closure or 'thunk', where all the arguments are bound in the
* constructor and is completely opaque. Callback::CallbackArg<T...>
* is a class which takes unbound arguments of the template types when
* the callback is dispatched, with any other arguments being bound at
* construction time. (The opaque Callback::Callback type is in fact
* just a typedef for Callback::CallbackArg<>: the two types are
* interchangeable.)
*
* The classes can represent static and non-static member functions
* and plain functions. In the case of a non-static member function,
* the object whose member function the callback represents must
* remain in existence until any invocations of the callback have
* completed. The function referred to must be one of void return
* type. A callback object can also be constructed from any function
* object, provided that it is of void return type (which would
* amongst other things enable, where necessary, the binding of the
* referenced object of a non-static member function by taking an
* internal copy of it using std::bind or by lambda capture).
*
* They are particularly useful where a callback object may need to be
* handed between threads.
*
* The classes can also be useful for general event passing when used
* together with the Callback::post() functions, or as the data
* argument of a call to g_signal_connect_data() in a case where a
* better design arises when passing arguments known at connect time
* by storing them in the callback object itself, or as the
* continuation for GIO async operations.
*
* These classes are also used in the Emitter/EmitterArg classes in
* emitter.h, which enable callbacks to be connected to an emitter and
* provide for automatic disconnection where a class object whose
* member a callback represents ceases to exist.
*
* The Callback::make() functions
* ------------------------------
*
* The templated helper Callback::make() functions make it trivial to
* create a callback object of the correct type. The ordinary
* Callback::make() functions (that is, those not taking a
* std::function object) provide for a maximum of five bound arguments
* to pass to the relevant function or class method, and an unlimited
* number of unbound arguments, but unbound arguments must be the last
* (trailing) arguments of the relevant function or method to be
* called if there is a bound argument. Callback/CallbackArg classes
* do not provide for a return value. If a result is wanted, users
* should pass an unbound argument by reference or pointer (or pointer
* to pointer).
*
* Although as mentioned above only five bound arguments are provided
* for by callbacks constructed by the ordinary Callback::make()
* functions, as any of those arguments can be a struct, any number of
* arguments can be passed as members of a struct or a std::tuple. In
* addition, a callback object can be constructed using
* Callback::make() from a std::function object, which can have any
* number of arguments bound to it, and in any order (that is, unbound
* arguments may precede bound arguments).
*
* The Callback::make() functions not taking a std::function object do
* a direct type mapping from the bound arguments of the function or
* method represented by the callback object to the arguments stored
* by the callback object. Bound value arguments of the relevant
* function or method to be called are therefore stored by value in
* the callback object. A bound argument can comprise a reference
* argument (T& or const T&) if the template parameters of the
* Callback::make() call are qualified by hand to avoid a type
* mismatch: see under "Usage" below for further particulars, and if
* the reference argument is non-const this allows the referenced
* argument to be mutated. However as this would result in the
* lifetime of the argument not being controlled by the callback
* object (it would not keep its own copy), it will often be unsafe to
* do so. (The documentation on Thread::JoinableHandle gives a usage
* where where binding a reference argument would be safe.)
*
* From version 2.0.0-rc3, the library also provides
* Callback::make_ref() functions, which force the callback object to
* keep a copy of the value passed where a target function argument is
* a const reference. It is therefore safe with const reference
* arguments. No explicit type qualification is required by
* Callback::make_ref(). In addition the Callback::make_ref()
* functions provide for more efficient passing of class type bound
* arguments (by l-value or r-value reference) than does
* Callback::make(): see further below.
*
* The Callback::make_ref() functions
* ----------------------------------
*
* In order to enable the widest variety of types to be accepted as
* arguments (including reference arguments in those cases where it is
* safe, and also string literals), as mentioned above when
* constructing a callback object from other than a std::function
* object, Callback::make() receives non-reference bound arguments by
* value, and if unoptimised these may be copied up to two times, and
* once more when the target function is dispatched. Where a bound
* argument is a pointer or a fundamental type (an integral or
* floating-point type), optimization by copy elision will reduce the
* number of times argument copying takes place when constructing a
* callback object to once, but the standard does not permit that with
* class types where the constructor or destructor have side effects
* or it cannot be ascertained whether they have side effects.
*
* Therefore, to cater for cases where a target function takes a class
* type argument by const reference or value, from version 2.0.0-rc3
* the Callback::make_ref() functions are provided. Unlike
* Callback::make(), when constructing a callback for a target
* function taking a const reference bound argument,
* Callback::make_ref() will force the callback object to keep a copy
* of the argument instead of a reference to that argument. This
* makes the use of const reference arguments safe (at the cost of the
* storing of that copy). It cannot be used with non-const
* references. In addition Callback::make_ref() automatically chooses
* the most efficient means of passing class type arguments for
* storage by the callback object, that is by l-value reference or
* r-value reference, as appropriate.
*
* In the case of a value argument, at callback dispatch time one
* additional copy will be made in the normal way when the target
* function is called, but in the case of a const reference argument
* no such additional copy will be made. What all this means is that,
* where bound arguments include a non-trivial class type, the most
* efficient and exception safe strategy is usually:
*
* 1. If that class type has a rvalue constructor, to have the target
* function take that type by const reference argument, and pass a
* newly constructed object of that type to Callback::make_ref() as a
* temporary (so that it is passed by r-value reference and stored in
* the callback object without any copying at all), or
* 2. To construct the object of the class type on free store and held
* by Cgu::SharedPtr, Cgu::SharedLockPtr or std::shared_ptr, have the
* target function take it by const Cgu::SharedPtr&, const
* Cgu::SharedLockPtr& or const std::shared_ptr&, and construct the
* callback object using Callback::make_ref().
*
* This flexibility of Callback::make_ref() has a downside: unlike
* Callback::make(), Callback::make_ref() cannot resolve overloaded
* functions by argument type. Where a function has two or more
* overloads taking the same number of arguments, explicit
* disambiguation by the user is required (see further below under
* Overloaded Functions).
*
* Summary: If a callback object's bound arguments are all simple
* fundamental types such as pointers (including C strings), integers
* or floating points, use Callback::make(). Where bound arguments
* include class types, use Callback::make_ref().
*
* The Callback::make_val() functions
* ----------------------------------
*
* The library also provides Callback::make_val() functions. These
* are provided to retain code compatibility with version 1.2 of the
* library. They were optimised for use where a target function takes
* bound arguments of class type by value, but are now deprecated and
* superseded by the automatic variable type mapping of
* Callback::make_ref(). Callback::make_ref() should now be used
* instead of Callback::make_val().
*
* Constructing callbacks from std::function objects
* -------------------------------------------------
*
* The Callback::make() factory functions can also construct a
* callback object from a std::function object, which would enable a
* callback to take more than 5 bound arguments, or to have a bound
* argument which is passed after (or mixed with) unbound arguments,
* or to have its own copy of the referenced object of a non-static
* member function bound to it.
*
* However, the genericity of the binding of arguments implemented in
* std::function and std::bind comes at a cost. Arguments bound to a
* std::function object can be copied a significant number of times
* (libstdc++ for example can copy class types four times when
* constructing a std::function object and two more times when
* executing the function, unless they have a r-value constructor, in
* which case they are copied twice and once respectively with two and
* one additional calls to the r-value constructor). Non-trivial
* class types should therefore only be passed as bound arguments to
* std::function objects by pointer or smart pointer.
*
* Note that the overload of Callback::make() for std::function
* objects has a version taking a r-value reference for the lossless
* passing through of temporaries to the callback object, and a
* version taking a const reference for std::function objects which
* are l-values. For std::function objects, Callback::make() and
* Callback::make_ref() are all synonyms (the way arguments are dealt
* with for std::function objects is determined by std::bind() and
* std::ref()).
*
* From version 2.0.9, in many uses it is better to pass a function
* object (such as the return value of std::bind(), or one generated
* by a lambda expression) to Callback::lambda(), which takes any
* arbitrary callable object directly as a template parameter.
*
* The Callback::lambda() functions
* --------------------------------
*
* Callback objects for C++11 lambda expressions can be constructed
* using Callback::make() by passing the lambda object via a temporary
* std::function object (see under Usage below for an example).
* However, from version 2.0.9 the Callback::lambda() factory function
* is provided enabling callbacks for C++11 lambda expressions to be
* constructed more directly. This is nice, as by using
* Callback::lambda() a callback can, for example, be executed by a
* glib main loop using Callback::post() with:
* @code
* using namespace Cgu;
* post(Callback::lambda<>([]() {std::cout << "Hello glib\n";})); // post() found by argument dependent lookup
* @endcode
* Further examples are given under Usage below.
*
* Callback::lambda() can construct a callback object from any
* arbitrary function object, such as the return value of std::bind().
* Using Callback::lambda() to construct such a callback object,
* rather than using Callback::make() with a temporary std::function
* object, will also be more efficient, as when executed it would
* normally avoid the additional virtual function call that would
* arise with std::function.
*
* When using Callback::lambda(), the unbound argument types must be
* specified explicitly (they cannot be deduced from the lambda
* expression).
*
* From version 2.0.10, Callback::lambda() can be called for lambda
* expressions which are declared mutable capturing bound arguments by
* value (in version 2.0.9, the function could only be called for
* non-mutable lambda expressions). From version 2.0.16, it can be
* passed callable objects which are lvalues as well as rvalues (prior
* to version 2.0.16, it could only be passed callable objects which
* are rvalues).
*
* One other feature of Callback::lambda() is that the callable object
* passed to it need not be of void return type. However, if the
* callable object does return a value, that value is discarded. If a
* result is wanted, an unbound reference or pointer argument should
* be passed when the callback is executed, to which the result can be
* assigned.
*
* If using lambda expressions with gcc, gcc-4.5 or greater is needed.
* The header file callback.h can be included without error with
* gcc-4.4, but callable objects cannot be constructed using C++11
* lambda syntax.
*
* Functors
* --------
*
* If a functor class of void return type is required (say for passing
* to a c++ algorithm or container, or for automatic lifetime
* management of the Callback object), the Callback::Functor and
* Callback::FunctorArg wrapper classes can be used. However, for
* many c++ algorithms where anonymous functors created as temporaries
* can be used, the std::ptr_fun(), std::mem_fn() and std::bind()
* factory functions or a lambda expression will be a more obvious
* choice. Callback::Functor and Callback::FunctorArg are to be
* preferred to std::function where value arguments are to be bound
* (see above), unless something other than a void return type is
* required.
*
* Callback::SafeFunctor and Callback::SafeFunctorArg classes are the
* same as Callback::Functor and Callback::FunctorArg classes, except
* that objects of the safe version may be passed and copied between
* threads and put in different containers in different threads (that
* is, the reference count maintained with respect to the contained
* callback object is thread-safe). They use a SharedLockPtr object
* to hold the referenced callback object.
*
* Memory allocation
* -----------------
*
* If the library is installed using the
* \--with-glib-memory-slices-compat or
* \--with-glib-memory-slices-no-compat configuration options, any
* Callback::Functor, Callback::FunctorArg, Callback::SafeFunctor or
* Callback::SafeFunctorArg objects constructed on free store (usually
* they won't be) will be constructed in glib memory slices. A
* contained Callback::Callback or Callback::CallbackArg object, which
* will always be constructed on free store, will be constructed in
* glib memory slices if the \--with-glib-memory-slices-no-compat
* configuration option is chosen.
*
* Usage
* -----
*
* For a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, int, const char*), usage for a fully bound
* callback or functor would be:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::Callback* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n");
* cb->dispatch();
* delete cb;
*
* Callback::Functor f{Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n")};
* f();
* @endcode
*
* Or for a partially bound callback or functor:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::CallbackArg<int, const char*>* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1);
* cb->dispatch(arg2, "Hello\n");
* delete cb;
*
* Callback::FunctorArg<int, const char*> f{Callback::make(my_obj, &MyClass::my_method, arg1)};
* f(arg2, "Hello\n");
* @endcode
*
* The syntax for the construction of a callback object representing a
* static member function with a signature void MyClass::my_func(int,
* const char*), or for a normal function, is similar to the
* non-static member function case, except that the call to
* Callback::make would comprise:
*
* @code
* Callback::make(&MyClass::my_func, arg1, arg2, "Hello\n");
* @endcode
* (fully bound), or
* @code
* Callback::make(&MyClass::my_func, arg1);
* @endcode
* (partially bound), and so on.
*
* To bind to reference arguments, the call to Callback::make() must
* be explicitly typed. For a class object my_obj of type MyClass,
* with a method void MyClass::my_method(int&), usage for a fully
* bound callback or functor would be:
*
* @code
* int arg = 1;
* Callback::Callback* cb =
* Callback::make<MyClass, int&>(my_obj, &MyClass::my_method, arg);
* @endcode
*
* Note however the caveats above about binding to reference
* arguments.
*
* No similar explicit typing is required by Callback::make_ref().
* Thus for a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, const Something&), usage for a fully bound
* callback or functor would be:
*
* @code
* int arg1 = 1;
* Something arg2;
* Callback::Callback* cb =
* Callback::make_ref(my_obj, &MyClass::my_method, arg1, arg2);
* @endcode
*
* From version 2.0.9, Callback::lambda() provides an easy
* way of dealing with lambda expressions, for example:
*
* @code
* Callback::Callback* cb;
* {
* std::string s("Hello");
* cb = Callback::lambda<>([=](){std::cout << s << std::endl;});
* }
* cb->dispatch(); // 's' is now out of scope, but it has been captured by value
* // by the lambda object and is now held by the callback object
* delete cb;
* @endcode
*
* With Callback::lambda(), the types of the unbound arguments must be
* explicitly specified as they cannot be deduced. Unbound arguments
* can comprise reference arguments. For example:
*
* @code
* int res;
* auto cb = Callback::lambda<int, int, int&>([](int j, int k, int& r) {r = j * k;});
* cb->dispatch(2, 3, res);
* std::cout << res << std::endl;
* delete cb;
* @endcode
*
* Callback::lambda() can take any function object, such as one
* returned by std::bind(). So, constructing a callback object
* representing a class object my_obj of type MyClass, with a method
* void MyClass::my_method(int, int, int, double, const char*), where
* a value is to be bound to the second argument could comprise:
*
* @code
* using namespace std::placeholders; // for _1, _2, _3 and _4
* int arg = 1;
* auto cb = Callback::lambda<int, int, double, const char*>(
* std::bind(&MyClass::my_method, &my_obj,
* _1, arg, _2, _3, _4)
* );
* cb->dispatch(5, 3, 10.2, "Hello\n");
* delete cb;
* @endcode
*
* Using std::bind, if the bound argument were a reference (that is,
* the signature of MyClass::my_method were (int, int&, int, double,
* const char*) and it were safe to do so (see above), it could be
* bound with std::ref(), as in:
*
* @code
* using namespace std::placeholders; // for _1, _2, _3 and _4
* int arg;
* auto cb = Callback::lambda<int, int, double, const char*>(
* std::bind(&MyClass::my_method, &my_obj,
* _1, std::ref(arg), _2, _3, _4)
* );
* @endcode
*
* Prior to version 2.0.9, lambda expressions and the return value of
* std::bind() would have to be passed by using a temporary
* std::function object and Callback::make, as follows:
*
* @code
* Callback::Callback* cb;
* {
* std::string s("Hello");
* cb = Callback::make(std::function<void()>{[=](){std::cout << s << std::endl;}});
* }
* cb->dispatch();
* delete cb;
* @endcode
*
* Overloaded functions
* --------------------
*
* Note that creating callbacks for overloaded functions can give rise
* to an ambiguity when using Callback::make(), arising from the fact
* that the callback object may have an unbound argument. For
* example:
*
* @code
* class MyClass {
* ...
* void add(int i);
* void add(int i, int j);
* void add(double d);
* };
* MyClass obj;
* using namespace Cgu;
* Callback::Callback* cb1 = Callback::make(obj, &MyClass::add, 1, 2); // ok
* Callback::Callback* cb2 = Callback::make(obj, &MyClass::add, 1.0); // ok
* Callback::Callback* cb3 = Callback::make(obj, &MyClass::add, 1); // ambiguous - compilation failure
* @endcode
*
* The third call to Callback::make() is ambiguous, as it could be
* creating a callback for either the function MyClass::add(int) with
* no unbound argument (that is, creating a Callback::Callback
* object), or the function MyClass::add(int, int) with an unbound int
* argument (that is, creating a Callback::CallbackArg<int> object).
* This situation could be disambiguated by specifically stating the
* type of the function which is to be chosen, namely, to instantiate
* the callback in the third call with:
*
* @code
* // either:
* Callback::Callback* cb3 =
* Callback::make(obj, static_cast<void (MyClass::*)(int)>(&MyClass::add), 1);
* // or:
* Callback::CallbackArg<int>* cb3 =
* Callback::make(obj, static_cast<void (MyClass::*)(int, int)>(&MyClass::add), 1);
* @endcode
*
* Callback::make_ref() is less capable than Callback::make() at
* deducing template types. It cannot resolve overloaded functions by
* examining the arguments passed to it. For example, take a class
* MyClass as follows:
*
* @code
* class MyClass {
* ...
* void add(int i, const double& d);
* void add(const int& j, const int& k);
* };
* @endcode
*
* Callback::make_ref() would require explicit disambiguation like
* this:
*
* @code
* Callback::Callback* cb1 =
* Callback::make_ref(obj, static_cast<void (MyClass::*)(int, const double&)>(&MyClass::add), 1, 2.2);
* Callback::Callback* cb2 =
* Callback::make_ref(obj, static_cast<void (MyClass::*)(const int&, const int&)>(&MyClass::add), 4, 5);
* @endcode
*
* Note also that, for CallbackArg objects created from std::function
* objects, the std::function constructors and the std::mem_fn() and
* std::bind() functions normally do not allow any function
* overloading without explicit disambiguation.
*
* Posting of callbacks
* --------------------
*
* This file also provides Callback::post() functions which will
* execute a callback in a glib main loop and can be used (amongst
* other things) to pass an event from a worker thread to the main
* program thread. In that respect, it provides an alternative to the
* Notifier class. It is passed a pointer to a Callback::Callback
* object created with a call to Callback::make() or
* Callback::lambda().
*
* To provide for thread-safe automatic disconnection of the callback
* if the object whose method it represents is destroyed before the
* callback executes in the main loop, include a Releaser as a public
* member of that object and pass the Releaser object as the second
* argument of Callback::post(). Note that for this to be race free,
* the lifetime of the remote object whose method is to be invoked
* must be determined by the thread to whose main loop the callback
* has been attached. When the main loop begins invoking the
* execution of the callback, the remote object must either wholly
* exist (in which case the callback will be invoked) or have been
* destroyed (in which case the callback will be ignored), and not be
* in some transient half-state governed by another thread.
*
* Advantages as against Notifier:
*
* 1. If there are a lot of different events requiring callbacks to be
* dispatched in the program from worker threads to the main
* thread, this avoids having separate Notifier objects for each
* event.
* 2. It is easier to pass arguments with varying values - they can be
* passed as arguments to the Callback::make functions and no
* special synchronisation is normally required (the call to
* g_source_attach() invokes locking of the main loop which will
* have the effect of ensuring memory visibility). With a Notifier
* object it may be necessary to use an asynchronous queue to pass
* variable values (or to bind a reference to the data, thus
* normally requiring separate synchronisation).
* 3. Although the callback would normally be sent for execution by
* the main program loop, and that is the default, it can be sent
* for execution by any thread which has its own
* GMainContext/GMainLoop objects. Thus callbacks can be passed
* for execution between worker threads, or from the main program
* thread to worker threads, as well as from worker threads to the
* main program thread.
*
* Disadvantages as against Notifier:
*
* 1. Less efficient, as a new callback object has to be created on
* freestore every time the callback is invoked, together with a
* new Emitter object if a Releaser is used to track the callback.
* 2. Multiple callbacks relevant to a single event cannot be invoked
* from a single call for the event - each callback has to be
* separately dispatched.
*/
#include <functional> // for std::less, std::function and std::hash<T*>
#include <utility> // for std::move and std::forward
#include <cstddef> // for std::size_t
#include <type_traits> // for std::remove_reference and std::remove_const
#include <glib.h>
#include <c++-gtk-utils/shared_ptr.h>
#include <c++-gtk-utils/param.h>
#include <c++-gtk-utils/cgu_config.h>
namespace Cgu {
namespace Callback {
/*
The CallbackArg class could be additionally templated to provide a
return value, but that would affect the simplicity of the
interface, and if a case were to arise where a result is needed, an
alternative is for users to pass an argument by reference or
pointer (or pointer to pointer) rather than have a return value.
*/
/* Declare the two basic interface types */
template <class... FreeArgs> class CallbackArg;
typedef CallbackArg<> Callback;
/* now the class definitions */
/**
* @class CallbackArg callback.h c++-gtk-utils/callback.h
* @brief The callback interface class
* @sa Callback namespace
* @sa FunctorArg SafeFunctorArg
*
* This provides the basic interface class that users will generally
* see. The template types are the types of the unbound arguments, if
* any. Callback::CallbackArg<> is typedef'ed to Callback::Callback.
*
* @b Usage
*
* For a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, int, const char*), usage for a fully bound
* callback would be:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::Callback* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n");
* cb->dispatch();
* delete cb;
* @endcode
*
* Or for a partially bound callback:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::CallbackArg<int, const char*>* cb =
* Callback::make(my_obj, &MyClass::my_method, arg1);
* cb->dispatch(arg2, "Hello\n");
* delete cb;
* @endcode
*
* Callback/CallbackArg classes do not provide for a return value. If
* a result is wanted, users should pass an unbound argument by
* reference or pointer (or pointer to pointer).
*
* For further background, including about the Callback::make(),
* Callback::make_ref() and Callback::lambda() functions read this:
* Callback
*/
template <class... FreeArgs>
class CallbackArg {
public:
/* Because dispatch() is a virtual function, we cannot templatise it
* with a view to preserving r-value forwarding of temporary objects
* passed as a free argument. But this would rarely be relevant
* anyway - it would only be relevant if the target function were to
* take an argument by r-value reference and a temporary were to be
* passed to it. In such a case virtual dispatch is at the cost of a
* copy of the temporary.
*/
/**
* This will execute the referenced function or class method
* encapsulated by this class. It will only throw if the dispatched
* function or class method throws, or if the copy constructor of a
* free or bound argument throws and it is not a reference argument.
* It is thread safe if the referenced function or class method is
* thread safe.
* @param args The unbound arguments to be passed to the referenced
* function or class method, if any.
* @note We use dispatch() to execute the callback, because the
* callback would normally be invoked through a base class pointer.
* To invoke it through operator()(), use the FunctorArg wrapper
* class.
*/
virtual void dispatch(typename Cgu::Param<FreeArgs>::ParamType... args) const = 0;
/**
* The constructor will not throw unless the copy constructor of an
* argument bound to the derived implementation class throws.
*/
CallbackArg() {}
/**
* The destructor will not throw unless the destructor of an argument
* bound to the derived implementation class throws.
*/
virtual ~CallbackArg() {}
/* these functions will be inherited by the derived callback classes */
#ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
CGU_GLIB_MEMORY_SLICES_FUNCS
#endif
};
/* The four basic functor types */
template <class... FreeArgs> class FunctorArg;
template <class... FreeArgs> class SafeFunctorArg;
typedef FunctorArg<> Functor;
typedef SafeFunctorArg<> SafeFunctor;
/* Functor friend functions */
// we can use built-in operator == when comparing pointers referencing
// different objects of the same type
/**
* Two FunctorArg objects compare equal if the addresses of the
* CallbackArg objects they contain are the same. This comparison
* operator does not throw.
*/
template <class... T>
bool operator==(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
return (f1.cb_s.get() == f2.cb_s.get());
}
/**
* Two FunctorArg objects compare unequal if the addresses of the
* CallbackArg objects they contain are not the same. This comparison
* operator does not throw.
*/
template <class... T>
bool operator!=(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
return !(f1 == f2);
}
// we must use std::less rather than the < built-in operator for
// pointers to objects not within the same array or object: "For
// templates greater, less, greater_equal, and less_equal, the
// specializations for any pointer type yield a total order, even if
// the built-in operators <, >, <=, >= do not." (para 20.3.3/8).
/**
* One FunctorArg object is less than another if the address of the
* CallbackArg object contained by the first is regarded by std::less
* as less than the address of the CallbackArg object contained by the
* other. This comparison operator does not throw.
*/
template <class... T>
bool operator<(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
return std::less<const CallbackArg<T...>*>()(f1.cb_s.get(), f2.cb_s.get());
}
/**
* Two SafeFunctorArg objects compare equal if the addresses of the
* CallbackArg objects they contain are the same. This comparison
* operator does not throw.
*/
template <class... T>
bool operator==(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
return (f1.cb_s.get() == f2.cb_s.get());
}
/**
* Two SafeFunctorArg objects compare unequal if the addresses of the
* CallbackArg objects they contain are not the same. This comparison
* operator does not throw.
*/
template <class... T>
bool operator!=(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
return !(f1 == f2);
}
/**
* One SafeFunctorArg object is less than another if the address of
* the CallbackArg object contained by the first is regarded by
* std::less as less than the address of the CallbackArg object
* contained by the other. This comparison operator does not throw.
*/
template <class... T>
bool operator<(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
return std::less<const CallbackArg<T...>*>()(f1.cb_s.get(), f2.cb_s.get());
}
} // namespace Callback
} // namespace Cgu
// doxygen produces long filenames that tar can't handle:
// we have generic documentation for std::hash specialisations
// in doxygen.main.in
#ifndef DOXYGEN_PARSING
/* These structs allow FunctorArg and SafeFunctorArg objects to be
keys in unordered associative containers */
namespace std {
template <class... T>
struct hash<Cgu::Callback::FunctorArg<T...>> {
typedef std::size_t result_type;
typedef Cgu::Callback::FunctorArg<T...> argument_type;
result_type operator()(const argument_type& f) const {
// this is fine: std::hash structs do not normally contain data and
// std::hash<T*> certainly won't, so we don't have overhead constructing
// std::hash<T*> on the fly
return std::hash<const Cgu::Callback::CallbackArg<T...>*>()(f.cb_s.get());
}
};
template <class... T>
struct hash<Cgu::Callback::SafeFunctorArg<T...>> {
typedef std::size_t result_type;
typedef Cgu::Callback::SafeFunctorArg<T...> argument_type;
result_type operator()(const argument_type& f) const {
// this is fine: std::hash structs do not normally contain data and
// std::hash<T*> certainly won't, so we don't have overhead constructing
// std::hash<T*> on the fly
return std::hash<const Cgu::Callback::CallbackArg<T...>*>()(f.cb_s.get());
}
};
} // namespace std
#endif // DOXYGEN_PARSING
namespace Cgu {
namespace Callback {
/* the functor classes */
/**
* @class FunctorArg callback.h c++-gtk-utils/callback.h
* @brief Functor class holding a Callback::CallbackArg object.
* @sa SafeFunctorArg
* @sa Callback namespace
*
* This class wraps a CallbackArg object. The callback object is kept
* by SharedPtr so the functor can be copied and offers automatic
* lifetime management of the wrapped callback object, as well as
* providing an operator()() function. Ownership is taken of the
* CallbackArg object passed to the constructor taking a CallbackArg
* pointer, so that constructor should be treated like a shared
* pointer constructor - only pass a newly allocated object to it (or
* copy construct it or assign to it from another existing FunctorArg
* object). The template types are the types of the unbound
* arguments, if any. Callback::FunctorArg<> is typedef'ed to
* Callback::Functor.
*
* The constructor taking a Callback::CallbackArg pointer is not
* marked explicit, so the results of Callback::make() can be passed
* directly to a function taking a Callback::FunctorArg argument, and
* implicit conversion will take place.
*
* @b Usage
*
* For a class object my_obj of type MyClass, with a method void
* MyClass::my_method(int, int, const char*), usage for a fully bound
* functor would be:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::Functor f{Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n")};
* f();
* @endcode
*
* Or for a partially bound functor:
*
* @code
* using namespace Cgu;
* int arg1 = 1, arg2 = 5;
* Callback::FunctorArg<int, const char*> f{Callback::make(my_obj, &MyClass::my_method, arg1)};
* f(arg2, "Hello\n");
* @endcode
*
* Callback/CallbackArg classes do not provide for a return value. If
* a result is wanted, users should pass an unbound argument by
* reference or pointer (or pointer to pointer).
*
* For further background, including about the Callback::make(),
* Callback::make_ref() and Callback::lambda() functions, and the use
* of these classes with std::function objects, read this: Callback
*/
template <class... FreeArgs>
class FunctorArg {
SharedPtr<const CallbackArg<FreeArgs...>> cb_s;
public:
/* Because CallbackArg::dispatch() is a virtual function, it is
* pointless templatising this function with a view to preserving
* r-value forwarding of temporary objects passed as a free argument,
* because the r-value typeness will be discarded in dispatch(). But
* this would rarely be relevant anyway - it would only be relevant if
* the target function were to take an argument by r-value reference
* and a temporary were to be passed to it. In such a case virtual
* dispatch is at the cost of a copy of the temporary.
*/
/**
* This will execute the function or class method referenced by the
* callback encapsulated by this object, or do nothing if this object
* has not been initialized with a callback. It will only throw if
* the executed function or class method throws, or if the copy
* constructor of a free or bound argument throws and it is not a
* reference argument. It is thread safe if the referenced function
* or class method is thread safe.
* @param args The unbound arguments to be passed to the referenced
* function or class method, if any.
*/
void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {
if (cb_s.get()) cb_s->dispatch(args...);
}
/**
* This function does not throw.
* @param f The assignor.
* @return The functor object after assignment.
*/
FunctorArg& operator=(const FunctorArg& f) {cb_s = f.cb_s; return *this;}
/**
* This function does not throw.
* @param f The functor to be moved.
* @return The functor object after the move operation.
*/
FunctorArg& operator=(FunctorArg&& f) {cb_s = std::move(f.cb_s); return *this;}
/**
* Two FunctorArg objects compare equal if the addresses of the
* CallbackArg objects they contain are the same. This comparison
* operator does not throw.
*/
friend bool operator== <>(const FunctorArg&, const FunctorArg&);
/**
* One FunctorArg object is less than another if the address of the
* CallbackArg object contained by the first is regarded by std::less
* as less than the address of the CallbackArg object contained by the
* other. This comparison operator does not throw.
*/
friend bool operator< <>(const FunctorArg&, const FunctorArg&);
friend struct std::hash<FunctorArg>;
/**
* Constructor of first FunctorArg holding the referenced callback.
* As it is not marked explicit, it is also a type conversion
* constructor.
* @param cb The CallbackArg object which the functor is to manage.
* @exception std::bad_alloc This might throw std::bad_alloc if
* memory is exhausted and the system throws in that case. Note that
* if such an exception is thrown, then this constructor will clean
* itself up and also delete the callback object passed to it.
* @note std::bad_alloc 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.
*/
FunctorArg(const CallbackArg<FreeArgs...>* cb): cb_s(cb) {}
/**
* The copy constructor does not throw.
* @param f The assignor
*/
FunctorArg(const FunctorArg& f): cb_s(f.cb_s) {}
/**
* The move constructor does not throw.
* @param f The functor to be moved.
*/
FunctorArg(FunctorArg&& f): cb_s(std::move(f.cb_s)) {}
/**
* Default constructor, where a Callback::CallbackArg object is to be
* assigned later (via the type conversion constructor and/or the
* assignment operator). This constructor does not throw.
*/
FunctorArg() {}
/* Only has effect if --with-glib-memory-slices-compat or
--with-glib-memory-slices-no-compat option picked */
CGU_GLIB_MEMORY_SLICES_FUNCS
};
/**
* @class SafeFunctorArg callback.h c++-gtk-utils/callback.h
* @brief Functor class holding a Callback::CallbackArg object, with
* thread-safe reference count.
* @sa FunctorArg
* @sa Callback namespace
*
* This class is the same as Callback::FunctorArg except that it will
* provide synchronisation of the reference count between threads.
* Use it where a functor wrapper object is to be passed between
* threads. The FunctorArg documentation gives details on usage.
*
* Callback::SafeFunctorArg<> is typedef'ed to Callback::SafeFunctor.
*
* For further background, read this: Callback
*/
template <class... FreeArgs>
class SafeFunctorArg {
SharedLockPtr<const CallbackArg<FreeArgs...>> cb_s;
public:
/**
* This will execute the function or class method referenced by the
* callback encapsulated by this object, or do nothing if this object
* has not been initialized with a callback. It will only throw if
* the executed function or class method throws, or if the copy
* constructor of a free or bound argument throws and it is not a
* reference argument. It is thread safe if the referenced function
* or class method is thread safe.
* @param args The unbound arguments to be passed to the referenced
* function or class method, if any.
*/
void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {
if (cb_s.get()) cb_s->dispatch(args...);
}
/**
* This function does not throw.
* @param f The assignor.
* @return The functor object after assignment.
*/
SafeFunctorArg& operator=(const SafeFunctorArg& f) {cb_s = f.cb_s; return *this;}
/**
* This function does not throw.
* @param f The functor to be moved.
* @return The functor object after the move operation.
*/
SafeFunctorArg& operator=(SafeFunctorArg&& f) {cb_s = std::move(f.cb_s); return *this;}
/**
* Two SafeFunctorArg objects compare equal if the addresses of the
* CallbackArg objects they contain are the same. This comparison
* operator does not throw.
*/
friend bool operator== <>(const SafeFunctorArg&, const SafeFunctorArg&);
/**
* One SafeFunctorArg object is less than another if the address of
* the CallbackArg object contained by the first is regarded by
* std::less as less than the address of the CallbackArg object
* contained by the other. This comparison operator does not throw.
*/
friend bool operator< <>(const SafeFunctorArg&, const SafeFunctorArg&);
friend struct std::hash<SafeFunctorArg>;
/**
* Constructor of first SafeFunctorArg holding the referenced
* callback. As it is not marked explicit, it is also a type
* conversion constructor.
* @param cb The CallbackArg object which the functor is to manage.
* @exception std::bad_alloc This might throw std::bad_alloc if
* memory is exhausted and the system throws in that case. Note that
* if such an exception is thrown, then this constructor will clean
* itself up and also delete the callback object passed to it.
* @note std::bad_alloc 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.
*/
SafeFunctorArg(const CallbackArg<FreeArgs...>* cb): cb_s(cb) {}
/**
* The copy constructor does not throw.
* @param f The assignor.
*/
SafeFunctorArg(const SafeFunctorArg& f): cb_s(f.cb_s) {}
/**
* The move constructor does not throw.
* @param f The functor to be moved.
*/
SafeFunctorArg(SafeFunctorArg&& f): cb_s(std::move(f.cb_s)) {}
/**
* Default constructor, where a Callback::CallbackArg object is to be
* assigned later (via the type conversion constructor and/or the
* assignment operator). This constructor does not throw.
* @note The reference count maintained with respect to the contained
* callback object is thread-safe, so SafeFunctorArg objects may be
* copied between threads by the implicit assignment operator and put
* in different containers in different threads. They use a
* SharedLockPtr object to hold the referenced callback object.
*/
SafeFunctorArg() {}
/* Only has effect if --with-glib-memory-slices-compat or
--with-glib-memory-slices-no-compat option picked */
CGU_GLIB_MEMORY_SLICES_FUNCS
};
/* the callback implementation classes */
template <class T, class... FreeArgs>
class Callback0: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(FreeArgs...);
private:
T* obj;
MemFunc func;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(free_args...);
}
Callback0(T& obj_, MemFunc func_): obj(&obj_), func(func_) {}
};
template <bool unref, class T, class BoundArg, class... FreeArgs>
class Callback1: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg, FreeArgs...);
private:
T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg, free_args...);
}
template <class Arg>
Callback1(T& obj_, MemFunc func_,
Arg&& arg_): obj(&obj_), func(func_), arg(std::forward<Arg>(arg_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, FreeArgs...);
private:
T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, free_args...);
}
template <class Arg1, class Arg2>
Callback2(T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_): obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...);
private:
T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, free_args...);
}
template <class Arg1, class Arg2, class Arg3>
Callback3(T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
class Callback4: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...);
private:
T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, arg4, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4>
Callback4(T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...);
private:
T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, arg4, arg5, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
Callback5(T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_,
Arg5&& arg5_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)),
arg5(std::forward<Arg5>(arg5_)) {}
};
/* const versions, for binding to const methods */
template <class T, class... FreeArgs>
class Callback0_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(FreeArgs...) const;
private:
const T* obj;
MemFunc func;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(free_args...);
}
Callback0_const(const T& obj_, MemFunc func_): obj(&obj_), func(func_) {}
};
template <bool unref, class T, class BoundArg, class... FreeArgs>
class Callback1_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg, FreeArgs...) const;
private:
const T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg, free_args...);
}
template <class Arg>
Callback1_const(const T& obj_, MemFunc func_,
Arg&& arg_): obj(&obj_), func(func_), arg(std::forward<Arg>(arg_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, FreeArgs...) const;
private:
const T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, free_args...);
}
template <class Arg1, class Arg2>
Callback2_const(const T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_): obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const;
private:
const T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, free_args...);
}
template <class Arg1, class Arg2, class Arg3>
Callback3_const(const T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
class Callback4_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...) const;
private:
const T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, arg4, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4>
Callback4_const(const T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)) {}
};
template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5_const: public CallbackArg<FreeArgs...> {
public:
typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...) const;
private:
const T* obj;
MemFunc func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
(obj->*func)(arg1, arg2, arg3, arg4, arg5, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
Callback5_const(const T& obj_, MemFunc func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_,
Arg5&& arg5_):
obj(&obj_), func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)),
arg5(std::forward<Arg5>(arg5_)) {}
};
/* for static class methods and non-class functions */
template <class... FreeArgs>
class Callback0_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(FreeArgs...);
private:
Func func;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(free_args...);
}
Callback0_static(Func func_): func(func_) {}
};
template <bool unref, class BoundArg, class... FreeArgs>
class Callback1_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(BoundArg, FreeArgs...);
private:
Func func;
typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(arg, free_args...);
}
template <class Arg>
Callback1_static(Func func_, Arg&& arg_): func(func_), arg(std::forward<Arg>(arg_)) {}
};
template <bool unref, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(BoundArg1, BoundArg2, FreeArgs...);
private:
Func func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(arg1, arg2, free_args...);
}
template <class Arg1, class Arg2>
Callback2_static(Func func_, Arg1&& arg1_,
Arg2&& arg2_): func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)) {}
};
template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...);
private:
Func func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(arg1, arg2, arg3, free_args...);
}
template <class Arg1, class Arg2, class Arg3>
Callback3_static(Func func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_):
func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)) {}
};
template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
class Callback4_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...);
private:
Func func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(arg1, arg2, arg3, arg4, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4>
Callback4_static(Func func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_):
func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)) {}
};
template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5_static: public CallbackArg<FreeArgs...> {
public:
typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...);
private:
Func func;
typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
func(arg1, arg2, arg3, arg4, arg5, free_args...);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
Callback5_static(Func func_,
Arg1&& arg1_,
Arg2&& arg2_,
Arg3&& arg3_,
Arg4&& arg4_,
Arg5&& arg5_):
func(func_),
arg1(std::forward<Arg1>(arg1_)),
arg2(std::forward<Arg2>(arg2_)),
arg3(std::forward<Arg3>(arg3_)),
arg4(std::forward<Arg4>(arg4_)),
arg5(std::forward<Arg5>(arg5_)) {}
};
// TODO: Version 2.0.9 provides a Callback_lambda class for callable
// objects which makes the specialized Callback_function class
// redundant. At an API break we can remove the Callback_function
// class and modify the Callback::make() helper function overload for
// std::function objects to construct a Callback_lambda object
// instead. Doing it now would not affect ABI compatibility as the
// library produces these only by base pointer, but a user may have
// instantiated them by hand in user code.
template <class... FreeArgs>
class Callback_function: public CallbackArg<FreeArgs...> {
std::function<void(FreeArgs...)> f;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {f(free_args...);}
Callback_function(const std::function<void(FreeArgs...)>& f_): f(f_) {}
Callback_function(std::function<void(FreeArgs...)>&& f_): f(std::move(f_)) {}
};
// generic class for callable objects such as lambdas
template <class Lambda, class... FreeArgs>
class Callback_lambda: public CallbackArg<FreeArgs...> {
// making 'l' mutable means that Callback_lamdba objects can contain
// mutable lambda expressions
mutable Lambda l;
public:
void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {l(free_args...);}
template <class L> Callback_lambda(L&& l_): l(std::forward<L>(l_)) {}
};
/* Convenience functions making callback objects on freestore. These
* can for example be passed as the first argument of the
* Thread::start() method in thread.h. They are also used by the
* Callback::post() function.
*/
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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).
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(FreeArgs...)) {
return new Callback0<T, FreeArgs...>{t, func};
}
/**
* DEPRECATED.
*
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(FreeArgs...)) {
return new Callback0<T, FreeArgs...>{t, func};
}
/**
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*
* Since 2.0.0-rc3
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(FreeArgs...)) {
return new Callback0<T, FreeArgs...>{t, func};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(BoundArg, FreeArgs...),
BoundArg arg) {
return new Callback1<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(BoundArg, FreeArgs...),
const BoundArg& arg) {
return new Callback1<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(BoundArg, FreeArgs...),
Arg&& arg) {
return new Callback1<true, T, BoundArg, FreeArgs...>{t, func, std::forward<Arg>(arg)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2) {
return new Callback2<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2) {
return new Callback2<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2,
class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2) {
return new Callback2<true, T, BoundArg1, BoundArg2, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3) {
return new Callback3<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3) {
return new Callback3<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3) {
return new Callback3<true, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4) {
return new Callback4<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4) {
return new Callback4<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4) {
return new Callback4<true, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4,
BoundArg5 arg5) {
return new Callback5<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4,
const BoundArg5& arg5) {
return new Callback5<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4,
Arg5&& arg5) {
return new Callback5<true, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5)};
}
/* const versions, for binding to const methods */
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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).
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(FreeArgs...) const) {
return new Callback0_const<T, FreeArgs...>{t, func};
}
/**
* DEPRECATED.
*
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(FreeArgs...) const) {
return new Callback0_const<T, FreeArgs...>{t, func};
}
/**
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*
* Since 2.0.0-rc3
*/
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(FreeArgs...) const) {
return new Callback0_const<T, FreeArgs...>{t, func};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(BoundArg, FreeArgs...) const,
BoundArg arg) {
return new Callback1_const<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(BoundArg, FreeArgs...) const,
const BoundArg& arg) {
return new Callback1_const<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(BoundArg, FreeArgs...) const,
Arg&& arg) {
return new Callback1_const<true, T, BoundArg, FreeArgs...>{t, func, std::forward<Arg>(arg)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
BoundArg1 arg1,
BoundArg2 arg2) {
return new Callback2_const<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
const BoundArg1& arg1,
const BoundArg2& arg2) {
return new Callback2_const<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2,
class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
Arg1&& arg1,
Arg2&& arg2) {
return new Callback2_const<true, T, BoundArg1, BoundArg2, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3) {
return new Callback3_const<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3) {
return new Callback3_const<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3) {
return new Callback3_const<true, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...) const,
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4) {
return new Callback4_const<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...) const,
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4) {
return new Callback4_const<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...) const,
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4) {
return new Callback4_const<true, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...) const,
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4,
BoundArg5 arg5) {
return new Callback5_const<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...) const,
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4,
const BoundArg5& arg5) {
return new Callback5_const<false, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...) const,
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4,
Arg5&& arg5) {
return new Callback5_const<true, T, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{t, func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5)};
}
/* for static class methods and non-class functions */
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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).
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(FreeArgs...)) {
return new Callback0_static<FreeArgs...>{func};
}
/**
* DEPRECATED.
*
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(FreeArgs...)) {
return new Callback0_static<FreeArgs...>{func};
}
/**
* Since this function constructs a callback which does not take a
* bound argument, it is a synonym for make() (the two are identical).
* @exception 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).
*
* Since 2.0.0-rc3
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(FreeArgs...)) {
return new Callback0_static<FreeArgs...>{func};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg, FreeArgs...),
BoundArg arg) {
return new Callback1_static<false, BoundArg, FreeArgs...>{func, arg};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg, FreeArgs...),
const BoundArg& arg) {
return new Callback1_static<false, BoundArg, FreeArgs...>{func, arg};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg, FreeArgs...),
Arg&& arg) {
return new Callback1_static<true, BoundArg, FreeArgs...>{func, std::forward<Arg>(arg)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2) {
return new Callback2_static<false, BoundArg1, BoundArg2, FreeArgs...>{func, arg1, arg2};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2) {
return new Callback2_static<false, BoundArg1, BoundArg2, FreeArgs...>{func, arg1, arg2};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class BoundArg1, class BoundArg2, class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2) {
return new Callback2_static<true, BoundArg1, BoundArg2, FreeArgs...>{func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3) {
return new Callback3_static<false, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func, arg1, arg2, arg3};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3) {
return new Callback3_static<false, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func, arg1, arg2, arg3};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class BoundArg1, class BoundArg2, class BoundArg3,
class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3) {
return new Callback3_static<true, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4) {
return new Callback4_static<false, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{func, arg1, arg2, arg3, arg4};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4) {
return new Callback4_static<false, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{func, arg1, arg2, arg3, arg4};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4) {
return new Callback4_static<true, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, FreeArgs...>{func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4)};
}
/**
* A convenience function to make Callback::CallbackArg objects
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
BoundArg1 arg1,
BoundArg2 arg2,
BoundArg3 arg3,
BoundArg4 arg4,
BoundArg5 arg5) {
return new Callback5_static<false, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{func, arg1, arg2, arg3, arg4, arg5};
}
/**
* DEPRECATED: use Callback::make_ref() instead.
*
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function receives an argument of
* class type by value which is to be a bound argument, so the
* compiler is not able to carry out copy elision when constructing
* the callback object.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class BoundArg1, class BoundArg2, class BoundArg3,
class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
const BoundArg1& arg1,
const BoundArg2& arg2,
const BoundArg3& arg3,
const BoundArg4& arg4,
const BoundArg5& arg5) {
return new Callback5_static<false, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{func, arg1, arg2, arg3, arg4, arg5};
}
/**
* An alternative function to make Callback::CallbackArg objects,
* which is for use where a target function either receives a class
* type bound argument by value, or receives a bound argument by
* reference to const in a case where the generated CallbackArg object
* is to store a copy of that argument instead of just keeping a
* reference.
* @exception 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 or move
* constructor of a bound argument throws.
*
* Since 2.0.0-rc3
*/
template <class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...),
Arg1&& arg1,
Arg2&& arg2,
Arg3&& arg3,
Arg4&& arg4,
Arg5&& arg5) {
return new Callback5_static<true, BoundArg1, BoundArg2, BoundArg3,
BoundArg4, BoundArg5, FreeArgs...>{func,
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3),
std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5)};
}
/* for std::function objects */
/**
* A convenience function to make Callback::CallbackArg objects from
* std::function objects.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(const std::function<void(FreeArgs...)>& f) {
return new Callback_function<FreeArgs...>{f};
}
/**
* DEPRECATED.
*
* A convenience function to make Callback::Callback objects from
* std::function objects. Since this function takes no bound argument
* (and bound arguments are bound into the std::function object), it
* is a synonym for make() (the two are identical).
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const std::function<void(FreeArgs...)>& f) {
return new Callback_function<FreeArgs...>{f};
}
/**
* A convenience function to make Callback::Callback objects from
* std::function objects. Since this function takes no bound argument
* (and bound arguments are bound into the std::function object), it
* is a synonym for make() (the two are identical).
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const std::function<void(FreeArgs...)>& f) {
return new Callback_function<FreeArgs...>{f};
}
/**
* A convenience function to make Callback::CallbackArg objects from
* std::function objects.
* @exception 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 of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(std::function<void(FreeArgs...)>&& f) {
return new Callback_function<FreeArgs...>{std::move(f)};
}
/**
* DEPRECATED.
*
* A convenience function to make Callback::Callback objects from
* std::function objects. Since this function takes no bound argument
* (and bound arguments are bound into the std::function object), it
* is a synonym for make() (the two are identical).
* @exception 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 or move
* constructor of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(std::function<void(FreeArgs...)>&& f) {
return new Callback_function<FreeArgs...>{std::move(f)};
}
/**
* A convenience function to make Callback::Callback objects from
* std::function objects. Since this function takes no bound argument
* (and bound arguments are bound into the std::function object), it
* is a synonym for make() (the two are identical).
* @exception 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 or move
* constructor of a bound argument throws and it is not a reference
* argument.
*/
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(std::function<void(FreeArgs...)>&& f) {
return new Callback_function<FreeArgs...>{std::move(f)};
}
// This helper function to construct Callback_lambda objects could be
// implemented as a further overload of Callback::make(). No best
// match ambiguities would arise, because even when Callback::make()
// is passed a function pointer without bound arguments, the overload
// of Callback::make taking a function pointer (as opposed to a
// generic callable object) would still comprise the best match.
// However, to construct Callback_lambda objects, the unbound
// arguments need to be specified by hand, which doesn't happen with
// Callback::make() (it would only be necessary to specify an explicit
// type where a mutable reference argument is to be bound to the
// callback object). It seems to me to be less confusing to the user
// therefore to have a separate Callback::lambda() helper function.
// However, if you disagree please let me know.
// template parameter packs do not need to be placed last in the case
// of function templates, as type deduction is available for the last
// parameter: there is in fact no function parameter pack in
// Callback::lambda() (function parameter packs must come last).
/**
* A convenience function to make Callback::CallbackArg objects from
* C++11 lambda expressions, or from any other arbitrary callable
* object. The types of the unbound arguments (if any) must be
* explicitly specified as template parameters, as they cannot be
* deduced. From version 2.0.10, this function can be called for
* lambda expressions which are declared mutable (in version 2.0.9,
* this function could only be called for non-mutable lambda
* expressions). From version 2.0.16, this function can be passed
* callable objects which are lvalues as well as rvalues (prior to
* version 2.0.16, it could only be passed callable objects which are
* rvalues).
* @exception 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 or move
* constructor of an object captured by the lambda expression throws.
*
* Since 2.0.9
*/
template <class... FreeArgs, class Lambda>
CallbackArg<FreeArgs...>* lambda(Lambda&& l) {
typedef typename std::remove_const<typename std::remove_reference<Lambda>::type>::type LType;
return new Callback_lambda<LType, FreeArgs...>{std::forward<Lambda>(l)};
}
} // namespace Callback
class Releaser;
namespace Callback {
/**
* Posts a callback for execution by a glib main loop. It is
* thread-safe provided that (if glib < 2.32 is used) g_thread_init()
* has been called. glib >= 2.32 does not require g_thread_init() to
* be called. This function will not throw.
* @param cb The callback object. Ownership is taken of this object,
* and it will be deleted when it has been finished with.
* @param priority The priority to be given to the callback in the
* main loop. 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_IDLE. 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
* @param context The glib main loop context in which the callback is
* to be executed (the default of NULL will cause the callback to be
* executed in the main program loop, and this is usually what is
* wanted).
* @note Cancellation of the receiving thread is blocked when the
* callback executes.
*/
void post(const Callback* cb, gint priority = G_PRIORITY_DEFAULT_IDLE,
GMainContext* context = 0);
/**
* Posts a callback for execution by a glib main loop. It is
* thread-safe provided that (if glib < 2.32 is used) g_thread_init()
* has been called. glib >= 2.32 does not require g_thread_init() to
* be called. This function will not throw.
* @param cb The callback object. Ownership is taken of this object,
* and it will be deleted when it has been finished with.
* @param r A Releaser object for automatic disconnection of the
* callback from the main loop.
* @param priority The priority to be given to the callback in the
* main loop. 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_IDLE. 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.
* @param context The glib main loop context in which the callback is
* to be executed (the default of NULL will cause the callback to be
* executed in the main program loop, and this is usually what is
* wanted).
* @exception std::bad_alloc This function might throw std::bad_alloc
* if memory is exhausted and the system throws in that case. If it
* does so, the Callback object will be disposed of.
* @exception Cgu::Thread::MutexError This method might throw
* Cgu:Thread::MutexError if initialisation of the mutex in a
* SafeEmitterArg object constructed by this method fails. If it does
* so, the Callback object will be disposed of. (It is often not
* worth checking for this exception, as it means either memory is
* exhausted or pthread has run out of other resources to create new
* mutexes.)
* @note 1. Cancellation of the receiving thread is blocked when the
* callback executes.
* @note 2. By virtue of the Releaser object, it is in theory possible
* (if memory is exhausted and the system throws in that case) that an
* internal SafeEmitterArg object will throw std::bad_alloc when
* emitting/executing the callback in the glib main loop, with the
* result that the relevant callback will not execute (instead the
* exception will be consumed and a g_critical() warning will be
* issued). This is rarely of any relevance because glib will abort
* the program if it is itself unable to obtain memory from the
* operating system. However, where it is relevant, design the
* program so that it is not necessary to provide a releaser object.
*/
void post(const Callback* cb, Releaser& r,
gint priority = G_PRIORITY_DEFAULT_IDLE, GMainContext* context = 0);
} // namespace Callback
} // namespace Cgu
#endif