I'm making a Gui API for games. Basically I have event callbacks in my class which are function pointers. I thought of directly letting the user = the function pointer ex:
widget->OnPaintCallback = myPaintFunc;
But I don't like how I cannot check for NULL or do anything else. It also makes my class feel exposed.
I also thought of having a setter for each callback, but that will get messy in the class (I have over 50)
I then thought of a function that asks for a string indicating which event the handler is for, and its function pointer. But that would evolve needlessly referencing documentation to know the string, and even more confusing for custom undocumented widgets.
Is there a better, cleaner alternative?
Thanks
Could casablankca's solution have multiple arguments?
I would suggest the Boost.Signals library. Something like this:
class Widget
{
public:
boost::signal<void (Paint &)> onPaint;
boost::signal<void (MouseMove &)> onMouseMove;
// ... etc
};
// later...
Widget myWidget;
myWidget.onPaint.connect(myPaintFunc);
// and to fire the event:
void Widget::DoPaint()
{
Paint data;
data.whatever = foo;
onPaint(data);
}
This has several advantages:
You can combine it with boost::bind (or C++0x version of bind if your compiler supports it) to allow you to bind member functions to event handlers.
You can attach multiple handlers to a single event. If you just use function pointers, then only a single function pointer can be assigned at a time.
The signals are strong-typed and flexible. You can have signals which take different types and numbers of parameters, and they'll all be resolved at compile-time.
I recommend taking a look at the boost.signals library, or libsigc++. These are very general libaries for managing things like event handlers. They do a lot more than what you are trying to do, but they'll give you ideas for what you may want from your design that you haven't thought of yet.
The more you use your callbacks the more you'll realize that you want more of the features in those libraries (like registering multiple callbacks, binding arguments, being more flexible with types, etc.) So even if you end up doing something simpler, it will be helpful to learn from mature designs.
But I don't like how I cannot check for NULL or do anything else
How about making the callback (OnPaintCallback) an object of a class that overloads operator =, that way you can do any additional checking and throw an exception if something goes wrong. You can also overload operator () so that you can call this object as if it were a simple function pointer.
Update: As for variable number of function arguments, there is no general way to do it, but if your maximum N is limited and small, you could use template specializations, for example: (I've omitted constructors, operator = and other details for clarity)
template<typename T, int N>
class Callback {
};
template<typename T>
class Callback<T, 1> {
T func;
template<typename A1>
void operator ()(A1 arg1) {
func(arg1);
}
};
template<typename T>
class Callback<T, 2> {
T func;
template<typename A1, typename A2>
void operator ()(A1 arg1, A2 arg2) {
func(arg1, arg2);
}
};
I know this is a hacky way to do it but at least your users won't see any of this: they'll get the same interface for all callbacks.
You can do an interface for each type of event handler you need. Not unlike Java does it. So for example you would have
class PaintCallback {
public:
virtual void paint() = 0;
};
Your event handler would inherit from the abstract class and implement the paint method. In the widget class you would keep a pointer (or a collection) for each handler.
Related
What I'm doing
I'm working on an event system. Basically there are "slots" which any member can chime into. All they need is an event name which it will be listening to, and a function. Since all the slots are stored I had to store them as a variable in a class.
The Problem
The function becomes unavailable when it's placed into the SlotBase class. I am wondering if there is a way to retain the function in the Slot class while storing in in the SlotBase class.
The Code
class SlotBase { };
// TC - Template Class
// TA - Template Arguments (types)
template <class TC, typename ...TA>
class Slot : public SlotBase {
public:
Slot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func);
}
template <int ...Is>
void SetSlot(TC* funcClass, void(TC::*func)(TA...), int_sequence<Is...>) {
function = std::bind(func, funcClass, placeholder_temp<Is>{}...);
}
void SetSlot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func, make_int_sequence<sizeof...(TA)>{});
}
std::function<void(TA...)> returnFunction(){
return function;
}
private:
std::function<void(TA...)> function;
};
//...
class RandomClass {
public:
void randomFunction(int a, float b, int c){ //do stuff };
}
//...
RandomClass randC;
SlotBase baseS;
Slot newSlot(&randC, &RandomClass::randomFunction);
baseS = newSlot;
//...
//Later on down the line when an event was found matching slot call slot function
baseS.returnFunction()(//Correct arguments go here - leaving this out (a lot more code));
I didn't include the code for the integer sequences in the 'std::bind' as it isn't related to the problem.
What I have tried
I know that if I use a Slot cast on the baseS variable that would give me the result but I am unable to do so because I don't know the templates that Slot will have.
I have seen many similar posts stating to make baseS a pointer (such as here) but I still don't understand how you would grab the function.
I think you need to start to accept that at some point if you want to use polymorph objects, you will need to create a virtual function in SlotBase. If you want to cast back to your type at creation before using the function, the polymorphism makes no sense, because you have carried the original type somewhere along with you to be able to do so, so why upcast anyway in the first time ?
If you really need to upcast, then you need to think about a RUNTIME solution to get back to access the derived functionality. In this case, this would mean you need to create a generic interface to your signals, so try to make a pure virtual method in SlotBase that will pack an undefined number of arguments, and implement that generic caller in your Slot so that it unpacks the arguments in order and calls your slot with the arguments. I don't know if variadic methods can be overriden though, that seems dubious. Otherwise you'll have to use boost::any or something to pack the arguments in a runtime collection.
I try to use a "simple" signal system with C++ 11. I use the following class :
http://geekswithblogs.net/raccoon_tim/archive/2011/09/28/lambdas-and-events-in-c.aspx
but I have a problems (I use Visual Studio 2012):
Problem description
I cannot create an event like this :
RREvent1Arg<void> testEvent;
The "void" is not an argument type !!
I have try with "template specialization" something like :
template<typename T1, typename T2> class Signaler {};
template<> class Signaler<T1> {};
template<> class Signaler<void> {};
But I got some compilation problems:
error C2065: 'T1' : undeclared identifier
Thanks for your help
Answer 1:
This RREvent1Arg from your article is not a general purpose signal/slot system. It isn't written in a generalized way. It's not surprising it hasn't been written to accommodate void, just as it isn't surprising that it doesn't handle a number of arguments besides 1 (given the name).
Note that it defines the callback handler as typedef std::function<void (T1)> Func; and then later tries to define things like void Call( T1 arg ). You can't declare a function in source like void foo( void arg ) in C++, and templates aren't allowed to create those either. There would be ways of using overloading to fix this, but there are also ways of taking variable arguments, etc.
Answer 2:
Offhand I'm not exactly sure what the rules are for using the capture features of lambda on "this" are, especially if it's getting wrapped up as a std::function. And because it's confusing I'd suggest saving this into another local variable, and capturing that by value:
static RREvent1Arg<int> testEvent;
class MyClass
{
int a;
void MyMethod()
{
MyClass *mc = this;
testEvent += [=mc](int) { mc->SignalReceived(); };
}
void SignalReceived()
{
this->a = 10;
}
};
But that's just me. Maybe the this capture is good style. Seems to cause problems for people in other questions.
I wrote this "simple signal library" that I use for a bunch of projects:
http://bitbucket.org/danielko/simplesignal
It doesn't handle accumulation of returned values because I don't consider that use case to be common enough to warrant the extra complexity.
What it does implement though is the signal/slot semantics; when you connect, you get a slot back that you need to keep alive for as long as you want to receive notifications from the signal. Destroying the slot (or calling disconnect() on it) will stop the signal from being delivered to the owner of the slot.
Hopefully it's simple and readable enough to be understandable; variadic templates take care of any number of arguments, no need for specialization.
I'm trying to construct a work queue of functions that need to be executed by one thread and can be fed by many threads. To accomplish this, I was planning on using the boost::packaged_task and boost::unique_future. The idea would be you would do:
Foo value = queue.add(myFunc).get();
which would block, until the function is executed. So queue.add(...) takes in a boost::function, and returns a boost::unique_future. Internally it then creates a boost::packaged_task using the boost::function for its constructor.
The problem I'm running into is that boost::function<...> won't be the same every time. Specifically, the return value for it will change (the functions, however, will never take any parameters). Thus, I have to have an add function that looks something like:
template <typename ResultType>
boost::unique_future<ResultType> add(boost::function<ResultType ()> f) {
boost::packaged_task<boost::function<ResultType ()> > task(f);
queue.push_back(task);
return task.get_future();
}
Okay, that doesn't seem too bad, but then I ran into the problem of how to define 'queue'. I think I have no choice but to use boost::any, since the types will not be constant:
std::list<boost::any> queue; // note: I'm not concerned with thread-safety yet
But then I run into a problem when I try to implement my executeSingle (takes just a single item off the queue to execute):
void executeSingle() {
boost::any value = queue.back();
boost::packaged_task<?> task = boost::packaged_task<?>(boost::move(value));
// actually execute task
task();
queue.pop_back();
}
The '?' denote what I'm unsure about. I can't call executeSingle with a template, as it's called from a separate thread. I tried using boost::any, but I get the error:
conversion from 'boost::any' to non-scalar type boost::detail::thread_move_t<boost:thread>' requested.
The funny part is, I actually don't care about the return type of packaged_task at this point, I just want to execute it, but I can figure out the template details.
Any insight would be greatly appreciated!
You should store boost::function<void()>'s. Note that boost::packaged_task<R>::operator() doesn't return anything; it populates the associated boost::future. In fact, even if it returned something you could still use boost::function<void()> since you'd still have no interest in the returned value: all you care about is to call queue.back()(). If this were the case boost::function<void()>::operator() would take care of discarding the returned value for you.
As a minor note, you might want to change the signature of your add method to be templated on a generic type Functor rather than a boost::function, and use boost::result_of to get the result type for boost::packaged_task.
My suggestion as a whole:
template<typename Functor>
boost::future<typename boost::result_of<Functor()>::type>
queue::add(Functor functor) // assuming your class is named queue
{
typedef typename boost::result_of<Functor()>::type result_type;
boost::packaged_task<result_type> task(functor);
boost::unique_future<result_type> future = task.get_future();
internal_queue.push_back(boost::move(task)); // assuming internal_queue member
return boost::move(future);
}
void
queue::executeSingle()
{
// Note: do you really want LIFO here?
queue.back()();
queue.pop_back();
}
EDIT
How to take care of move-semantics inside queue::add
typedef typename boost::result_of<Functor()>::type result_type;
typedef boost::packaged_task<result_type> task_type;
boost::shared_ptr<task_type> task = boost::make_shared<task_type>(functor);
boost::unique_future<result_type> future = task->get_future();
/* boost::shared_ptr is possibly move-enabled so you can try moving it */
internal_queue.push_back( boost::bind(dereference_functor(), task) );
return boost::move(future);
where dereference_functor could be:
struct dereference_functor {
template<typename Pointer>
void
operator()(Pointer const& p) const
{
(*p)();
}
};
You could also substitute the bind expression for the much clearer
boost::bind(&task_type::operator(), task)
which also doesn't require a custom functor. However if there are multiple overloads of task_type::operator() this might need disambiguation; the code could also break if a future change in the Boost.Thread introduce an overload.
You use old-fashioned virtual functions. Define a base class task_base with a virtual execute method, then define a template derived class which holds a specific task instance. Something along the lines:
struct task_base {
virtual void execute() = 0;
};
template<typename ResultType>
struct task_holder : task_base {
task_holder(boost::packaged_task<boost::function<ResultType ()> >&& task)
: m_task(task) { }
void execute() {
m_task();
}
private:
boost::packaged_task<boost::function<ResultType ()> > m_task;
};
And define your queue to hold unique_ptr<task_base>. This is essentially what boost::any does, only you'd be using a specific function, namely execute.
NOTE: Untested code! And I'm still not very familiar with rvalue references. This is just to give you the idea of how the code would look.
Somewhat belatedly, but you might want to consider using Boost.Asio instead of rolling your own queue-runner solution.
While this grew up as an I/O library it does support asynchronous calls just like this. Simply define an io_service somewhere, run it inside a thread, and then post functors to get called on that thread.
Is there any template available in boost for RAII. There are classes like scoped_ptr, shared_ptr which basically work on pointer. Can those classes be used for any other resources other than pointers. Is there any template which works with a general resources.
Take for example some resource which is acquired in the beginning of a scope and has to be somehow released at the end of scope. Both acquire and release take some steps. We could write a template which takes two(or maybe one object) functors which do this task. I havent thought it through how this can be achieved, i was just wondering are there any existing methods to do it
Edit: How about one in C++0x with support for lambda functions
shared_ptr provides the possibility to specify a custom deleter. When the pointer needs to be destroyed, the deleter will be invoked and can do whatever cleanup actions are necessary. This way more complicated resources than simple pointers can be managed with this smart pointer class.
The most generic approach is the ScopeGuard one (basic idea in this ddj article, implemented e.g. with convenience macros in Boost.ScopeExit), and lets you execute functions or clean up resources at scope exit.
But to be honest, i don't see why you'd want that. While i understand that its a bit annoying to write a class every time for a one-step-aquire and one-step-release pattern, you are talking about multi-step-aquire and -release.
If its taken multiple steps, it, in my opinion, belongs in an appropiately named utility class so that the details are hidden and the code in place (thus reducing error probability).
If you weigh it against the gains, those few additional lines are not really something to worry about.
A more generic and more efficient (no call through function pointer) version is as follows:
#include <boost/type_traits.hpp>
template<typename FuncType, FuncType * Func>
class RAIIFunc
{
public:
typedef typename boost::function_traits<FuncType>::arg1_type arg_type;
RAIIFunc(arg_type p) : p_(p) {}
~RAIIFunc() { Func(p_); }
arg_type & getValue() { return p_; }
arg_type const & getValue() const { return p_; }
private:
arg_type p_;
};
Example use:
RAIIFunc<int (int), ::close> f = ::open("...");
I have to admit I don't really see the point. Writing a RAII wrapper from scratch is ridiculously simple already. There's just not much work to be saved by using some kind of predefined wrapper:
struct scoped_foo : private boost::noncopyable {
scoped_foo() : f(...) {}
~scoped_foo() {...}
foo& get_foo() { return f; }
private:
foo f;
};
Now, the ...'s are essentially the bits that'd have to be filled out manually if you used some kind of general RAII template: creation and destruction of our foo resource. And without them there's really not much left. A few lines of boilerplate code, but it's so little it just doesn't seem worth it to extract it into a reusable template, at least not at the moment. With the addition of lambdas in C++0x, we could write the functors for creation and destruction so concisely that it might be worth it to write those and plug them into a reusable template. But until then, it seems like it'd be more trouble than worth. If you were to define two functors to plug into a RAII template, you'd have already written most of this boilerplate code twice.
I was thinking about something similar:
template <typename T>
class RAII {
private:
T (*constructor)();
void (*destructor)(T);
public:
T value;
RAII(T (*constructor)(), void (*destructor)(T)) :
constructor(constructor),
destructor(destructor) {
value = constructor();
}
~RAII() {
destructor(value);
}
};
and to be used like this (using OpenGL's GLUquadric as an example):
RAII<GLUquadric*> quad = RAII<GLUquadric*>(gluNewQuadric, gluDeleteQuadric);
gluSphere(quad.value, 3, 20, 20)
Here's yet another C++11 RAII helper: https://github.com/ArtemGr/libglim/blob/master/raii.hpp
It runs a C++ functor at destruction:
auto unmap = raiiFun ([&]() {munmap (fd, size);});
I have a custom Menu class written in C++. To seperate the code into easy-to-read functions I am using Callbacks.
Since I don't want to use Singletons for the Host of the Menu I provide another parameter (target) which will be given to the callback as the first parameter (some kind of workaround for the missing "this" reference).
Registration-Signature
AddItem(string s, void(*callback)(void*,MenuItem*), void* target = NULL)
Example of a Registration
menu->AddItem(TRANSLATE, "translate", &MyApp::OnModeSelected);
Example of a Handler
/* static */
void MyApp::OnModeSelected(void* that, MenuItem* item) {
MyApp *self = (MyApp*)that;
self->activeMode = item->text;
}
Is there anything one could consider dirty with this approach? Are there maybe better ones?
Your approach requires the callback functions to either be free functions or static members of a class. It does not allow clients to use member functions as callbacks. One solution to this is to use boost::function as the type of the callback:
typedef boost::function<void (MenuItem*)> callback_type;
AddItem(const std::string& s, const callback_type& callback = callback_type());
Clients can then use boost::bind or boost::lambda to pass in the callback:
menu->AddItem("Open", boost::bind(&MyClass::Open, this));
Another option is to use boost::signals which allows multiple callbacks to register for the same event.
I like your approach. One alternative would be to declare an interface, which is in some sense the "OO equivalent" of a callback:
class IMenuEntry {
public:
virtual void OnMenuEntrySelected(MenuItem* item) = 0;
};
The registration signature would become
AddItem(string s, IMenuEntry * entry);
And the method implementation
class MyApp : public IMenuEntry {
public:
virtual void OnMenuEntrySelected(MenuItem* item){
activeMode = item->text;
}
}
The interface approach would allow you to avoid the "void * workaround" for the missing this pointer.
You could take a look at using boost::bind.
menu->AddItem(TRANSLATE,
"translate",
boost::bind( &MyApp::OnModeSelected, this, _1, _2 ));
I don't see anything wrong except that the function pointer signature is hard to read. But, I would probably observer pattern to achieve this.
I'd highly recommend looking at boost::function and boost:bind for this. Learning it will make your function binding a hundred times easier.
Read this white-paper. It builds various techniques for a callback mechanism by analysing the performance, usability and other tradeoffs in quite a detail. I found it a hard read though :-(
Your could use a functor to encapsulate your callback. This would allow you to use either a C-style function or an object interface to provide the callback.