How to use std::bind for adding member callback to a messenger system - c++

I am currently trying to implement a messenger system for my game engine. It uses function callbacks of the form:
typedef std::function<void(const Message &)> Callback;
I want all objects to be able to subscribe to a message of a specific type (where the type is just a string). Subscribing means adding their "onEvent" function to the dictionary of callbacks.
mutable std::map<std::string, std::vector<Callback>> callbackDictionary;
The update function then calls these functions and passes the according message (from which the "onEvent" functions can get their data)
for each (auto message in messageList)
{
// find the list of respective callbacks
auto it = callbackDictionary.find(message->GetType());
// If there are callbacks registered for this message type
if (it != callbackDictionary.end())
{
// call every registred callback with the appropreate message
for each (auto callback in it->second)
callback(*message);
}
}
Now, my problem is that I am not quite sure how to bind these "onEvent" functions. I have just recently switched to C++11 and the concept of function objects and std::bind is quite new to me. So here is what I have tried:
messageBus.Subscribe("Message/Click",std::bind(&ClickableComponent::OnClick, this));
where the ClickableComponent::OnClick function has the required signature:
void OnClick(const Message &);
and the Subscribe function just adds the passed function to the dictionary
void Messenger::Subscribe(std::string type, Callback callbackFunction) const
{
callbackDictionary[type].push_back(callbackFunction);
}
(The push_back is used because there is a vector of callbacks for each type)
The code seems fine to me but the line:
messageBus.Subscribe("Message/Click", std::bind(&ClickableComponent::OnClick, this));
Gives me the error:
picture of the error discription
I have tried all kinds of stuff like forwarding the Messenger reference and using placeholders, but I have the feeling that I am doing something else wrong. Also, better idea on how to implement this messenger system are appreciated ^^
Thanks for your help!

std::bind is not necessary in your case, lambda function would do just fine:
messageBus.Subscribe("Message/Click", [this](const Message& msg) { OnClick(msg); });
std::bind is more useful in specific cases of metaprogramming.
But if you're curios enough to see how to use std::bind:
messageBus.Subscribe("Message/Click",
std::bind(&ClickableComponent::OnClick, this, std::placeholders::_1));
Here, as you see, you missed std::placeholders::_1. Your functor signature is void(const Message&), but you try to store a member function which signature can be regarded as void(ClickableComponent*, const Message&). To partially apply some arguments (what std::bind does) you need to specify arguments that you'd like to bind and arguments that you leave unbound.
Lambda is preferred because usually it's shorted, more flexible and more readable.

Related

C++ Use a class non-static method as a function pointer callback in freeRTOS xTimerCreate

I am trying to use marvinroger/async-mqtt-client that in the provided examples is used together with freertos timers that use a callback that gets invoked whenever the timer expire. The full example is here.
I wanted to create a singleton class to enclose all the connection managing part and just expose the constructor (through a getInstance) and a begin function that other than setting the callbacks, creates the timers for reconnection.
The class looks like (I simplified by removing useless parts):
class MqttManager : public Singleton<MqttManager> {
public:
virtual ~MqttManager() = default;
void begin();
protected:
MqttManager();
void connectToMqtt(TimerHandle_t xTimer);
void WiFiEvent(WiFiEvent_t event);
void onConnect(bool sessionPresent);
std::unique_ptr<AsyncMqttClient> client;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
};
While my issue is when I try to pass the connectToMqtt callback to the timer.
MqttManager::MqttManager() {
this->client = std::unique_ptr<AsyncMqttClient>(new AsyncMqttClient());
// use bind to use a class non-static method as a callback
// (works fine for mqtt callbacks and wifi callback)
this->client->onConnect(std::bind(&MqttManager::onConnect, this, std::placeholders::_1));
WiFi.onEvent(std::bind(&MqttManager::WiFiEvent, this, std::placeholders::_1));
// Here it fails
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)nullptr, &MqttManager::connectToMqtt, this, std::placeholders::_1);
The error is:
cannot convert 'void (MqttManager::)(TimerHandle_t) {aka void (MqttManager::)(void*)}' to 'TimerCallbackFunction_t {aka void ()(void)}' for argument '5' to 'void* xTimerCreate(const char*, TickType_t, UBaseType_t, void*, TimerCallbackFunction_t)'
Now, from here, having in mind that the problem is around having a pointer to a non-static method that needs somehow to be casted to a free function pointer, three doubts arise:
Why on earth the std::bind "approach" works for WiFi.onEvent but not for xTimerCreate? They seem pretty similar to me... WiFi is typedef void (*WiFiEventCb)(system_event_id_t event); while the timer typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );
How can I make this work? Is there a cast or a better approach?
Is this bad practice? My goal here was to enclose mqtt and wifi functions and callbacks in a neat class easily recognizable, organized and maintainable; but I guess that sometimes you just obtain the opposite result without noticing...
FreeRTOS code is plain old C. It knows nothing about C++, instance methods, function objects, etc. It takes a pointer to a function, period. As Armandas pointed out, WiFi.onEvent on the other hand is C++, lovingly written by someone to accept output from std::bind().
There is a workaround. When you read the xTimerCreate API docs, there is a sneaky little parameter pvTimerID which is effectively user-specified data. You can use this to pass a pointer to your class and later retrieve it from inside the callback function using pvTimerGetTimerID(). With a class pointer you can then forward the callback to your C++ class. See example below.
It's good practice to try to hide private class methods and data. Unfortunately this only works well if you're working entirely in C++ :) If calling into C libraries (like FreeRTOS) I find myself breaking such idealistic principles occasionally.
Here's how I'd do it. I use a lambda (without context) as the actual callback function because it's throwaway wrapper code, and the C libraries happily accept it as a plain old function pointer.
auto onTimer = [](TimerHandle_t hTmr) {
MqttManager* mm = static_cast<MqttManager*>(pvTimerGetTimerID(hTmr)); // Retrieve the pointer to class
assert(mm); // Sanity check
mm->connectToMqtt(hTmr); // Forward to the real callback
}
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, static_cast<void*>(this), onTimer);
std::bind returns a callable object, not a function pointer. It works with WiFi.onEvent because there is an overload taking a std::function:
typedef std::function<void(arduino_event_id_t event, arduino_event_info_t info)> WiFiEventFuncCb;
// ...
wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
Solution
Create a static function for the timer callback and simply get the MqttManager instance as you would from anywhere else.

What does this size_t in the lambda do? C++ code

I'm new to programming in C++, and I came across this syntax. Could someone explain the point of the size_t in this syntax?
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
It's the type of the argument passed to the function. The argument is not used in the function. Hence, it is not named. Only the type of the argument is there.
The type of the argument is there presumably because the client to which the lambda expression is passed expects it to have an argument of type size_t. The client has no way of knowing how the argument is used in the lambda expression or whether it is used at all.
This is like callbacks where your callback receive data from the caller and you do whatever you want with the data .
So if you don't need the data you can skip naming the parameter as it's unreferenced
You can see more examples about callbacks by reading the documentation of some winapi functions especially which enum things . e.g EnumWindows , EnumChildWindows EnumProc ....
As others have said, the lambda expression
[=](size_t)
{
return fileStream->close();
}
is being passed to a method call
.then()
To shed some additional light: usually, a method called .then() is part of a Futures callback interface. The then() method is called on a Future<T> object, where T is some type. It will expect a callback parameter. This causes callback chaining: when the Future<T> is fulfilled, we will have a T, and at this point in time the callback is invoked with that T.
In your case, T = size_t. So presumably, the Future object that .then() is called on returns a size_t, which is then passed to the lambda [=] (size_t) { ... }. The lambda then discards the size_t because it doesn't need it.
What's the point of taking the size_t parameter if it doesn't need it? Well, maybe the original Future object was some kind of read call, and it stored the result somewhere else (i.e. the work is done by side-effect) and returned the number of bytes it read (the size_t). But the callback is just doing some cleanup work and doesn't care about what was read. It would be like the following synchronous code:
size_t readFile(char* buf) {
// ... store stuff in buf
return bytesRead;
}
auto closeFileStream(size_t) {
return fileStream->close();
}
closeFileStream(readFile(&buf));
In terms of Futures, it's probably something more like:
Future<size_t> readFile(char* buf) {
// ... asynchronously store stuff in buf
// and return bytesRead as a Future
}
auto closeFileStream(size_t) {
return fileStream->close();
}
readFile(&buf)
.then(closeFileStream)
.get(); // wait synchronously

passing boost bind handlers as arguments to asio bind handlers

Are nested boost::bind permissible, and if so what am I doing wrong? I can nest lambda in bind successfully, but not bind in bind.
First example
The simple case
I can manage the standard use boost::bind to pass a complex completion handler invocation where a simple one taking only error code is needed:
socket->receive(buffer, boost::bind(...));
Nested case
but if I want to encapsulate a combination of boost asio operations (e.g. multi-stage async_connect and async_ssl_handshake).
My outer operation will be something like:
connect_and_ssl(socket, boost::bind(...));
and my first stage definition will pass the outer handler on to the second completion in another bind, so that the outer handler can be invoked at the end:
template<typename Socket, typename Handler>
void connect_and_ssl(Socket socket, Handler handler)
{
socket.async_connect(endpoint,
boost::bind(&w::handle_connect, this, socket, handler, boost::asio::placeholders::error));
};
template<typename Socket, typename Handler>
void handle_connect(Socket socket, Handler handler, const boost::system::error_code& ec) {
socket->async_handshake(handler);
}
however handler which is a boost::bind really does not like being part of another boost bind. I get a whole screen full of errors, about not being able to determine the type, and others.
Lambdas work
But I find that I can easily use lambdas instead:
template<typename Socket, typename Handler>
void connect_and_ssl(Socket socket, Handler handler)
{
socket.async_connect(endpoint,
[=](const boost::system::error_code& ec) { handle_connect(socket, handler, ec); } );
};
why? Lambdas are so much easier to write, and understand, but do they make possible something that was impossible with nested binds, or was I just expressing the binds wrongly?
Second example
Simple case
although this will compile:
m_ssl_socket->async_read_some(buffer, m_strand->wrap(handler));
Nested case
when converting to be also invoked from a strand:
m_strand->post(boost::bind(&boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>::async_read_some, m_ssl_socket, buffer, m_strand->wap(handler)));
it will no longer compile - no doubt due to the strand->wrap being inside a boost::bind
Lambda
However the lamda version compiles and runs fine:
m_strand->post([=](){m_ssl_socket->async_read_some(buffer, m_strand->wrap(handler)); } );
I can't work it out, but I'm very glad for lamdas.
Nested bind requires protect.
Boost Bind has it.
In C++11 you have to define one yourself (e.g. using reference_wrapper).

Call back routine

In the Learning OpenCV book, I came to the term callback, and sometimes used with routine as callback routine.
What do we mean when we saycallback?
Thanks.
What is a Callback function?
In simple terms, a Callback function is a function that is not called explicitly by the programmer. Instead, there is some mechanism that continually waits for events to occur, and it will call selected functions in response to particular events.
This mechanism is typically used when an operation(function) takes a long time for execution and the caller of the function does not want to wait till the operation is complete, but does wish to be intimated of the outcome of the operation. Typically, Callback functions help implement such an asynchronous mechanism, wherein the caller registers to get inimated about the result of the time consuming processing and continuous other operations while at a later point of time, the caller gets informed of the result.
A practical example:
Windows event processing:
virtually all windows programs set up an event loop, that makes the program respond to particular events (e.g button presses, selecting a check box, window getting focus) by calling a function. The handy thing is that the programmer can specify what function gets called when (say) a particular button is pressed, even though it is not possible to specify when the button will be pressed. The function that is called is referred to as a callback.
A source Code Illustration:
//warning: Mind compiled code, intended to illustrate the mechanism
#include <map>
typedef void (*Callback)();
std::map<int, Callback> callback_map;
void RegisterCallback(int event, Callback function)
{
callback_map[event] = function;
}
bool finished = false;
int GetNextEvent()
{
static int i = 0;
++i;
if (i == 5) finished = false;
}
void EventProcessor()
{
int event;
while (!finished)
{
event = GetNextEvent();
std::map<int, Callback>::const_iterator it = callback_map.find(event);
if (it != callback_map.end()) // if a callback is registered for event
{
Callback function = *it;
if (function)
{
(*function)();
}
else
{
std::cout << "No callback found\n";
}
}
}
}
void Cat()
{
std::cout << "Cat\n";
}
void Dog()
{
std::cout << "Dog\n";
}
void Bird()
{
std::cout << "Bird\n";
}
int main()
{
RegisterCallBack(1, Cat);
RegisterCallback(2, Dog);
RegisterCallback(3, Cat);
RegisterCallback(4, Bird);
RegisterCallback(5, Cat);
EventProcessor();
return 0;
}
The above would output the following:
Cat
Dog
Cat
Bird
Cat
Hope this helps!
Note:
Imported this answer from one of my old answers here.
"I don't call it by myself, but the system (or some others) will call it". That's callback.
They mean that you pass a pointer to a procedure to OpenCV. This will be called back when something happens. This can e.g. seen at cvSetMouseCallback(). The function referenced by the pointer will be called whenever the mouse moves.
Following the Holywood principle "Don't call us, we call you", a callback is a reference to a function which is passed to another function.
The callback will be called by the function it is given to for instance when data is available or certain processing steps need to be performed.
"Routine" in this context is the same as "function". The term goes back to older languages (like Fortran) that made a difference between functions, that returns values, and (sub)routines that don't.
"Callback" is a technique where you provide a pointer to one of your functions ("routines") to the system/API/framework and the system/API/framework would call it back when it feels like doing so. So a callback routine, or simply a callback, is a function that's intended for such usage.
In strictly object languages (like Java) they typically use listeners and delegates for that. The callback technique, in its C++ form, has the advantage that's it's compatible with non-object-oriented languages like classic C.
EDIT: in the Microsoft C run-time library, this technique is used for qsort() function. The compare argument is a function pointer to a callback routine. It's called by the RTL whenever two array elements need to be compared. It's not a typical example 'cause all the calls to compare happen before the qsort() call returns.
In Win32 API, callbacks are a staple. The window procedure is a prime example - you pass a pointer to it in the WNDCLASS structure, the system calls the procedure back as the message arrive. In this case, the callback routine is invoked long after the RegisterClass() - for the whole lifetime of the window.
In POSIX/Unix/Linux, the signal processing function is an example. See the signal() syscall description.
Callback functions are function which are not called explicitly such functions automatically invoked after some event occurs, for example after pressing​ "ctrl+c" SIGINT signal generated so automatically handler will execute.

Call function after certain time has elapsed

I'm making a GUI API (for games, not an OS) and would like to implement animated buttons. I'd like to be able to create timed events, but, within the class.
example:
class TextBox
{
void changeColor(int color);
void createTimedEvent(func* or something, int ticks);
void animate()
{
createTimedEvent(changeColor(red),30);
}
};
So in this example, the timer would call the class instance's changeColor function, with argument red, after 30 ms. Is there a way to do this?
Basically, a function to call a function, which could be a function from a instancable class, wit n arguments, after a given interval has expired.
The precision of the timer is not a big deal for me.
Thanks
I believe you could make this work portably using Boost.Asio - this is primarily designed for async I/O but I see no reason why the timer code cannot be used in other contexts. See this example for how to kick off a timer which calls back your code after expiry.
The only proviso I noticed is that you have to call ioservice::run in some thread with the ioservice instance you used here, or the callbacks will not happen.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/)
{
std::cout << "Hello, world!\n";
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
// ensure we call io.run() from some thread or callbacks will not happen
// other app logic
return(0);
}
There is also a discussion of this very topic on MSDN blogs here by the author of the library.
I'd welcome anybody showing otherwise, but as far as I know, you'd need to deal with this in steps. The first step is to create a bound function -- i.e., take the function you specify, and create an object that, when you invoke it, in turn invokes the specified function with the specified parameters. Using Boost/TR1/C++0x bind, that much would look something like this:
std::tr1::function<void (int)> func(std::tr1::bind(&TextBox::changColor, this, red));
That makes func an object that will invoke TextBox::changeColor(red) when it's called. There is one minor problem with this though: func is an object, not really a function. Syntactically, using it looks like calling a function, but that's an illusion created by the C++ compiler; trying to pass that object's address to something that will use it as the address of a function will fail (probably pretty spectacularly). Unfortunately, at least in Windows, there's no way to designate an arbitrary parameter that will be passed to a timer callback function (though you could probably manage to do it in the nIdEvent parameter with some really gross casting, something like:
void callback(HWND, UINT, UINT_PTR f, DWORD) {
typedef std::tr1::function<void (int)> function;
function *func = reinterpret_cast<function *>(f);
(*func)();
}
To make this a bit cleaner, instead of casting the address to an unsigned integer, I'd consider saving the address of the callback in an array, and passing its index in the array instead:
void callback(HWND, UINT, UINT_PTR f, DWORD) {
callback_functions[f]();
}
That leaves the really non-portable part: actually getting the system to invoke that function after the right length of time. Though most modern systems have one, each is still unique. Under Windows (for one example) you could do something like this:
callback_functions[++N] = func;
SetTimer(hWnd, N, 30, callback);
For such a simple idea, that's all too ugly and complex an answer, but I honestly don't know of anything much less complex that'll work. If you have almost any reasonable choice in the matter, I'd use something else. Also note that this is really a stream-of-consciousness sketch -- none of the code has been compiled, much less really tested. I can't see a good reason the general idea shouldn't work, but it might take a fair amount of effort to flesh it out to something that really does (e.g., I've mostly neglected management of the "callback_functions" array).