I have an event driven application. I want to keep the event handler ( EventHandler
class capable of many/all events) a common implementation - while allowing the EventSource
be changeable (specifically - at compile time).
To couple the EventHandler
with the EventSource
, I will have to store an instance of handler within the EventSource
. I tried to store handlers of various forms:
EventHandler
(that has public handler methods defined in concrete EventHandler
's std::function
- this provided greatest flexibility However, in both cases, the latency in calling the target method/lambda was quite high (on my test setup about 250ns) - and to worse, was inconsistent. May be due to virtual table and/or heap allocation and/or type erasure ???
In order to reduce this latency, I want to make use of templates.
The best I could come up with is:
template <typename EventHandler>
class EventSource1
{
EventHandler* mHandler;
public:
typedef EventHandler EventHandlerType;
void AssignHandler (EventHandler* handler)
{
this->mHandler = handler;
}
void EventuallyDoCallback (int arbArg)
{
this->mHandler->CallbackFunction (arbArg);
}
};
template <EventSourceType>
class EventSourceTraits
{
typedef EventSourceType::EventHandlerType EventHandlerType;
static void AssignHandler (EventSourceType& source, EventHandlerType* handler)
{
source.AssignHandler(handler);
}
};
class EventHandler
{
public:
void CallbackFunction (int arg)
{
std::cout << "My callback called\n";
}
};
int main ()
{
EventSource1<EventHandler> source; /// as one can notice, EventSource's need not to know the event handler objects.
EventHandler handler;
EventSourceTraits<EventSource1>::AssignHandler (source, &handler);
}
This method impose a restriction that all my EventSource
's to be a template classes.
Question is : Is this best way to achieve consistent and low latency to callback? Can this code be improved to avoid the event source classes be completely independent of event handler objects' type ?
Is this best way to achieve consistent and low latency to callback?
As suggested in the comments to the question, I'd rather try and measure to know if that's really a problem and what's the best alternative for you.
There doesn't exist the best way , it mostly depends on the actual problem.
can this code be improved to avoid the event source classes be completely independent of event handler objects' type ?
Maybe the following can be a good point from which to start to achieve that:
#include <iostream>
class EventSource1
{
using invoke_t = void(*)(void *C, int value);
template<typename T, void(T::*M)(int)>
static void proto(void *C, int value) {
(static_cast<T*>(C)->*M)(value);
}
invoke_t invoke;
void *handler;
public:
template<typename T, void(T::*M)(int) = &T::CallbackFunction>
void AssignHandler (T* ref)
{
invoke = &proto<T, M>;
handler = ref;
}
void EventuallyDoCallback (int arg)
{
invoke(handler, arg);
}
};
class EventHandler
{
public:
void CallbackFunction (int arg)
{
std::cout << "My callback called: " << arg << std::endl;
}
};
int main ()
{
EventSource1 source;
EventHandler handler;
source.AssignHandler(&handler);
source.EventuallyDoCallback(42);
}
See it on wandbox .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.