Low latent callback in C ++

I have an event driven application. I want the event handler (a EventHandlerclass capable of many / all events) to be a common implementation, allowing to change EventSource(in particular - at compile time).

To link EventHandlerto EventSource, I will need to save the handler instance in EventSource. I tried to store handlers of various forms:

  • pointer to an interface EventHandler(which has open handler methods defined in a particularEventHandler
  • instance std::function- this provided maximum flexibility.

However, in both cases, the latency when calling the target method / lambda was quite high (about 250 ns on my test setup) - and, even worse, it was inconsistent. Maybe due to a virtual table and / or heap allocation and / or type erasure ???

To reduce this delay, I want to use patterns.

The best I could come up with was:

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 need not to know the event handler objects.
    EventHandler handler;

    EventSourceTraits<EventSource1>::AssignHandler (source, &handler);
}

This method restricts all my EventSourceclasses to be template classes.

Question : Is this the best way to achieve consistent and low latency for callback? Is it possible to improve this code to avoid the event source classes being completely independent of the type of event handler objects?

+4
source share
1

?

, , .
, .

, , ?

, :

#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);
}

wandbox.

+1

Source: https://habr.com/ru/post/1669014/


All Articles