C++ 中的低延迟回调

Low latency callback in C++

我有一个事件驱动的应用程序。我想保持事件处理程序(EventHandler class 能够处理 many/all 事件)一个通用的实现 - 同时允许 EventSource 可变(特别是 - 在编译时)。

为了将 EventHandlerEventSource 相结合,我将不得不在 EventSource 中存储一个 handler 的实例。我尝试存储各种形式的 handlers

然而,在这两种情况下,调用目标 method/lambda 的延迟都非常高(在我的测试设置中约为 250ns)——更糟糕的是,不一致。可能是由于virtual table and/or heap allocation and/or type erasure ???

为了减少延迟,我想使用模板。

我能想到的最好的是:

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

此方法施加了一个限制,即我的所有 EventSource 都必须是模板 class。

问题是:这是实现一致且低延迟回调的最佳方式吗?是否可以改进此代码以避免事件源 class 完全独立于事件处理程序对象的类型?

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 ?

也许以下内容可以作为开始实现该目标的一个很好的起点:

#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 上查看。