I have a two-layer object structure where the contained object has a deadline_timer and the outer object has the handler function, as:
class Internal
{
asio::deadline_timer t;
public:
void QueueTick(void (*handler)(boost::system::error_code const&))
{
t.expires_from_now(posix_time::millisec(250));
t.async_wait(handler);
}
};
class ForClients
{
Internal I;
void OnTick(boost::system::error_code const&) { /*...*/ }
void Init()
{
I.QueueTick(boost::bind(&cdevXcite::OnTick, this, _1));
}
};
The QueueTick() call is failing to compile in MSVS 2008 with "cannot convert parameter 1 from 'boost::_bi::bind_t' to 'void (__cdecl *)(const boost::system::error_code &)'".
If I make the timer member public and make a direct call to I.t.async_wait() with the same argument, it succeeds. Clearly, the handler's signature is more special than what I've used in the QueueTick declaration; however, I can't find a symbol that defines it and I don't know how to interpret the metaprogramming going on inside the basic_deadline_timer<> template.
An asio timer's async_wait can be called with any callable type that can be called with a boost::system::error_code const& argument. There isn't a single type anywhere that defines it, it just has to be callable with the documented argument type.
The type of your QueueTick parameter is one such callable type, a pointer to a plain ol' non-member function with the right signature:
void QueueTick(void (*handler)(boost::system::error_code const&))
But the result of boost::bind is a class type with an overloaded operator() which is not convertible to that function pointer type.
There are a few ways to solve this, but the simplest is probably to follow async_wait itself and write QueueTick as a function template, accepting any type:
class Internal
{
asio::deadline_timer t;
public:
template<WaitHandle>
void QueueTick(WaitHandle handler)
{
t.expires_from_now(posix_time::millisec(250));
t.async_wait(handler);
}
};
The rest of the code would be unchanged.
If that's not an option (e.g. because QueueTick needs to be virtual) then you could use boost::function with can hold any callable object of the right signature:
class Internal
{
asio::deadline_timer t;
public:
typedef boost::function<void(boost::system::error_code const&)> handler_type;
void QueueTick(handler_type handler)
{
t.expires_from_now(posix_time::millisec(250));
t.async_wait(handler);
}
};
This will have a small overhead compared to the template version, due to constructing the boost::function object.
If you can use C++11, you can do something like:
class Internal
{
asio::deadline_timer t;
public:
void QueueTick(const std::function<void(const boost::system::error_code&)>& handler)
{
t.expires_from_now(posix_time::millisec(250));
t.async_wait(handler);
}
};
class ForClients
{
Internal I;
void OnTick(const boost::system::error_code& ec) { /*...*/ }
void Init()
{
I.QueueTick([this](const boost::system::error_code& ec) { OnTick(ec); });
}
};
Related
I have this to accomplish.
Function DoJob() would take different "verify" functor to verify things in different way.
It's possible to pass some variable such as "message" to verify function.
Or, it's possible not to pass any parameter to verify function.
and, now, DoJob is a function of a singleton class. I can use getInstance() anywhere to get this class.
Based on this, how do I define the DoJob and verify interface?
Thanks,
The singleton class:
struct MySingleton
{
static MySingleton* getInstance();
// DoJob for verify functions that need a message.
void DoJob(void (*verify)(std::string const&), std::string const& message)
{
verify(message);
}
// DoJob for verify functions that don't need a message.
void DoJob(void (*verify)())
{
verify();
}
};
A function to be used to verify.
void verify1(std::string const& message)
{
// Do something with message
}
Use the singleton and the verify function.
MySingleton::getInstance()->DoJob(verify1, "A message");
You can use a C++11 variadic template to accomplish this.
class Foo {
//...
public:
static Foo & getInstance() {
static Foo instance;
return instance;
}
template <typename V, typename ...X>
void DoJob (V verify, X... x) {
verify(x...);
}
};
struct Vvoid {
void operator () (void) {}
};
struct Vstring {
void operator () (std::string) {}
};
void Vfunction (void) {}
//...
Foo &f = Foo::getInstance();
f.DoJob(Vvoid());
f.DoJob(Vstring(), "msg");
f.DoJob(Vfunction);
Note that Vvoid and Vstring are true functors (object instances that can be called like a function with the () operator). But, the template syntax allows any callable instance to be passed in, including regular function pointers (e.g., Vfunction).
Follow the link for a working demo.
I have a problem now. I am trying to encapsulatie boost::signal and boost::bind into my own Event class.
class MyEvent
{
private:
boost::signal<void ()> Sig;
public:
void Subscribe(.........)
{
Sig.connect(boost:bind(.........);
}
void Raise()
{
Sig();
}
};
I have try to pass function pointer in the Subscribe function's signature and visual studio just gives me tones of errors.
I dont know how to write the signature of Subscribe and What to pass into boost::bind, ideally I will have boost::bind(&MyClass::MyHandler, &MyClassObject) in Subscribe function and will Call it outside like MyEventObject.Subscribe(&MyClass::MyHandler, &MyClass).
Can any people help me fill that two blanks?
You can just make Subscribe a template:
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
class MyEvent
{
private:
boost::signals2::signal<void ()> Sig;
public:
template<class SlotClass>
void Subscribe(void (SlotClass::*func)(), SlotClass *obj)
{
Sig.connect(boost::bind(func, obj));
}
void Raise()
{
Sig();
}
};
struct Test
{
void f()
{}
};
int main()
{
MyEvent myEvent;
Test test;
myEvent.Subscribe(&Test::f, &test); // test must outlive myEvent!
}
Note however that such a wrapper limits its user very much: with original signal he could connect any callable of any kind created in various ways, while with your wrapper he must pass a pointer to member function and a pointer to object.
I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...
I am working on an event daemon in C++ that I would like to use member function callbacks. Basically an event queue would collect events which the daemon continuously services. There is a base class Event struct with an ID and all events would derive from it. I would like the methods registered for each event to use the derived event type in their signature.
struct Event
{
unsigned int eventId;
};
struct EventA : public Event
{
unsigned int x;
unsigned int y;
};
// and struct EventB, EventC (use your imagination...)
const unsigned int EVENT_A = 1;
const unsigned int EVENT_B = 2;
const unsigned int EVENT_C = 3;
class Foo
{
public:
void handlerMethod_A(const EventA& e);
void handlerMethod_B(const EventB& e);
};
class Bar
{
public:
void handlerMethod_C(const EventC& e);
};
Then the Daemon would allow these classes to subscribe their member functions using their 'this' pointer.
class EventDaemon
{
public:
void serviceEvents();
template <class CallbackClass, class EventType>
void subscribe(
const unsigned int eventId,
CallbackClass* classInstancePtr,
void (CallbackClass::*funcPtr)(EventType));
private:
Queue<Event*> eventQueue_;
};
So outside this class you could do something like:
EventDaemon* ed = new EventDaemon();
Foo* foo = new Foo();
Bar* bar = new Bar();
ed->subscribe(EVENT_A, foo, Foo::handlerMethod_A);
ed->subscribe(EVENT_B, foo, Foo::handlerMethod_B);
ed->subscribe(EVENT_C, bar, Bar::handlerMethod_C);
And the EventDaemon loop would be along the lines of
void EventDaemon::serviceEvents()
{
while (true)
{
if (eventQueue_.empty())
{
// yield to other threads
}
else
{
// pop an event out of the FIFO queue
Event e* = eventQueue_.pop();
// somehow look up the callback info and use it
classInstancePtr->*funcPtr(reinterpret_cast<?*>(e));
}
}
}
So my question is how I can store the 'this' pointers and member function pointers in some sort of array by event ID. That way I could look up the 'classInstancePtr' and 'funcPtr' by using e->eventId and the event type as well for the reinterpret cast.
You are working too hard. Use boost functions:
http://www.boost.org/doc/libs/1_47_0/doc/html/function.html
These work whether you have a object or not. They will increase your compile time.
Note, whenever you come across these types of questions where you know many people must have had the same problem, there is probably a simple option and, if it is not in the standard library, it is probably in boost.
In response to Nick, I'm constantly throwing boost function objects into vectors and whatnot.
I've found that, while boost function objects can hold object references, having them do so can lead to bugs with object lifetimes and it is better to have them hold copies of the class objects (you run into the same bugs however you try to hold a reference to a object instance that you don't necessarily control the lifetime of). The pattern:
class Foo
{
struct Member
{
// member variable definitions
};
shared_ptr<Member> m_; // the only real member variable
public:
// etc. including the all-important copy
// constructor and assignment operator and
// don't forget the member function that gets stuck into
// the boost function as a callback!
};
where all the member variables get held in a shared_ptr allows for good performance and you don't have to worry about lifetimes of objects held by function objects because you can copy them by value. Threaded code (what I always seem to be writing nowadays) needs additional things like at least one boost mutex element in Member or some other way to assure values don't get stomped on.
boost::function [or, if your system supports it, std::function] will take care of holding the this pointer quite well, with the added benefit of not requiring an actual object if it isn't necessary. So instead of void (SomeType::*)(EventA) you have std::function<void(EventA)>, and you call std::bind as appropriate.
subscribe(EVENT_A, std::bind(&foo::handleEventA, &foo, std::placeholders::_1));
A trivial wrapper function can be used to provide the same signature as you originally proposed and hide the nasty placeholders.
You do, of course, still have the issue of each event type having its own signature, and the need to ensure you use the correct Event ID code. In both cases, your base Event type can help out. Your callback need not accept an EventA&; it can accept an Event&, and dynamic_cast it to an EventA at runtime. For the ID, query the type directly.
struct Event {
virtual void ~Event() { }
virtual int ID() =0;
};
template<typename E>
struct EventHelper : Event {
virtual int ID() { return E::EventID; }
};
struct EventA : EventHelper<EventA> {
static const int EventID = 89;
};
Now, if you have an Event* object [when you go to dispatch your events], you can do p->ID() to get the appropriate ID, and if you have a EventA type [when you register your callbacks] you can do EventA::EventID.
So now, all you have to store is a std::function<void(const Event&)> and an associated int value for each of your callbacks, no matter what the actual type of event you have.
void subscribe(int id, std::function<void(const Event&)> f) {
callbacks.insert(std::make_pair(id, f));
}
template<typename E>
void subscribe(std::function<void(const Event&)> f) {
subscribe(E::EventID, f);
}
template<typename O, typename E>
void subscribe(O* p, void (O::*f)(const Event&)) {
subscribe<E>(std::bind(f, p, std::placeholders::_1));
}
You still have the issue that user error when subscribing can result in a function being called incorrectly. If you've used dynamic_cast correctly within the callback, this will get caught at runtime, but a compile time check would be nice. So what if we automate that dynamic_cast? For this step, I'm going to use c++11 lambdas, but it can be implemented in C++03 as well using a variety of methods.
template <class CallbackClass, class EventType>
void subscribe(CallbackClass* classInstancePtr, void (CallbackClass::*funcPtr)(EventType)) {
subscribe<EventType::EventID>([&](const Event& e) {
(classInstancePtr->*funcPtr)(dynamic_cast<const EventType&>(e));
});
}
So now we've gone full circle back to your original interface where your callbacks accept the actual type they are going to be working on, but internally you've squeezed them all into a common signature.
Okay, so I finished an implementation of my original desired interface. I was looking through Dennis' answer but eventually got lead to functors and I realized what I was looking for was a simple polymorphic solution. I failed to grasp before that I could create a non-templated base class with which to use for storing templated classes in vectors/arrays. I think this is what mheyman was trying to tell me... so I apologize I didn't get it right away. Just to clarify though I was really looking for the implementation solution for my own benefit and knowledge, not just a 3rd party library to get the job done. So I guess I would be looking for how Boost functions work, not just that they exist and are awesome.
If anyone is still interested here are the important parts of what I ended up with (minus some extraneous stuff and error checking):
EventFunctor is basically a pointer to member function template class
EventFunctorBase is the non-templated base class used to store them in a vector
The Event is dynamic cast using the templated type before being used to invoke the callback
class EventDaemon
{
public:
template <class CallbackClass, class EventType>
void subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
private:
EventFunctorBase* callbacks_[MAX_NUM_EVENTS];
};
template <class CallbackClass, class EventType>
void EventDaemon::subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
{
callbacks_[eventId] = new EventFunctor<CallbackClass,EventType>(callbackClassInstancePtr,funcPtr);
}
class EventFunctorBase
{
public:
EventFunctorBase();
virtual ~EventFunctorBase();
virtual void operator()(const Event& e)=0;
};
template <class CallbackClass, class EventType>
class EventFunctor : public EventFunctorBase
{
public:
EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
virtual void operator()(const Event& e);
private:
CallbackClass* callbackClassInstancePtr_;
void (CallbackClass::*funcPtr_)(const EventType&);
};
template <class CallbackClass, class EventType>
EventFunctor<CallbackClass,EventType>::EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
:
callbackClassInstancePtr_(callbackClassInstancePtr),
funcPtr_(funcPtr)
{
}
template <class CallbackClass, class EventType>
/*virtual*/ void EventFunctor<CallbackClass,EventType>::operator()(const Event& e)
{
(callbackClassInstancePtr_->*funcPtr_)(dynamic_cast<const EventType&>(e));
}
EventDaemon loop
while (true_)
{
if (eventQueue_->empty())
{
// yield to other threads
}
else
{
Event* e = eventQueue_.pop();
(*(callbacks_[e->ID]))(*e);
}
}
My final steps here will be to try and remove the need to have the developer define an ID for each event... of course this might end up a new post later this week.
So I'm working on this event management class. I'm storing a list of pointers to member functions of the signature void (Event*) where Event is just a struct that stores some random data at the moment.
typedef boost::function<void(Event*)> Callback;
typedef vector<Callback> CallbackList;
class EventManager
{
public:
template<typename T>
void RegisterEventHandler(const std::string& type, void (T::*handler)(Event*), T* obj)
{
mCallbackList[type].push_back(boost::bind(handler, obj, _1));
}
void DispatchEvent(const std::string& type, Event* evt)
{
for(CallbackList::iterator it = mCallbackList[type].begin(); it != mCallbackList[type].end(); ++it)
{
Callback callback = (*it);
callback(evt);
}
}
private:
hash_map<std::string, CallbackList> mCallbackList;
};
I'm wondering, if it's possible for me to derive different versions of Event, and pass pointers to those member functions into this class? Currently I'm trying this.
class MouseEvent : public Event
{
public:
int testMouseData1;
int testMouseData2;
int testMouseData3;
};
class HelloWorld
{
public:
void Display(MouseEvent* evt)
{
cout << "Hello, world!" << endl;
}
};
int main(void)
{
MouseEvent* evt = new MouseEvent();
HelloWorld* world = new HelloWorld();
eventManager->RegisterEventHandler("testType", &HelloWorld::Display, world);
return 0;
}
This gives me the following error in XCode.
error: no matching function for call to 'EventManager::RegisterEventHandler(const char [9], void (HelloWorld::*)(MouseEvent*), HelloWorld*&)'
Do you know how I can safely pass in a pointer that's expecting a derived class in its function signature? Thanks.
So I found a solution that seems to be working for me, but I'm not sure if it's entirely safe to do. I changed the RegisterEventHandler method to cast all of the function pointers that I send in to the same type...
template<typename T1, typename T2>
void RegisterEventHandler(const String& type, T1 handler, T2* obj)
{
void (T2::*evtHandler)(Event*) = (void (T2::*)(Event*)) (handler);
mCallbackList[type].push_back(boost::bind(evtHandler, obj, _1));
}
now it all seems to just work as I originally intended. But I'm pretty new to all this so I'm not entirely sure if this is a safe thing to do. Any thoughts? Thanks
If your prototype expects "Event" type then you need to make sure the void Display(MouseEvent* evt) function is accepting the "Event" type. So change it to void Display(Event *evt) Then inside the call you can typecast it back to a MouseEvent, assuming that the caller passed an actual MouseEvent, referenced as an "Event".
Secondly, I believe you may have some other issues with the way you are calling RegisterEventHandler since it is in a template but you are not specifying the template type.