Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 404
rat6 Avatar asked Oct 29 '22 12:10

rat6


1 Answers

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.

like image 200
skypjack Avatar answered Nov 15 '22 06:11

skypjack