C ++中的低延迟回调

时间:2017-02-07 06:35:18

标签: c++ callback std-function

我有一个事件驱动的应用程序。我希望保持事件处理程序(EventHandler类能够执行许多/所有事件)的常见实现 - 同时允许EventSource可更改(特别是在编译时)。

要将EventHandlerEventSource结合起来,我必须在EventSource中存储处理程序的实例。我试图存储各种形式的处理程序

  • 指向EventHandler接口的指针(具有在具体EventHandler中定义的公共处理程序方法
  • std::function的实例 - 这提供了最大的灵活性

然而,在这两种情况下,调用目标方法/ lambda的延迟都非常高(在我的测试设置上大约250ns) - 更糟糕的是,它是不一致的。可能是由于虚拟表和/或堆分配和/或类型擦除???

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

我能想到的最好的是:

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都是模板类。

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

1 个答案:

答案 0 :(得分:2)

  

这是实现回调一致且低延迟的最佳方式吗?

正如问题评论中所建议的那样,我宁愿尝试并衡量以了解这是否真的是一个问题以及什么是最适合您的选择。
不存在最佳方式,它主要取决于实际问题。

  

可以改进此代码,以避免事件源类完全独立于事件处理程序对象&#39;输入?

以下可能是开始实现这一目标的好点:

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