简体   繁体   中英

Low latency callback in C++

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:

  • pointer to an interface of EventHandler (that has public handler methods defined in concrete EventHandler 's
  • instance of 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM