在单独的线程上调用 boost signals2 槽

call boost signals2 slot on a separate thread

如何在不阻塞发出信号的线程的情况下在单独的线程上调用 boost signals2 槽?我想通过 QueuedConnection 参数获得 Qt5 QObject::connect 的功能;有关 Qt5 的详细信息,请参阅 Threads and QObjects。也就是说,我需要能够发出 boost signals2 信号,而不可能阻塞发出信号的线程;连接的插槽从单独的“事件”线程调用。

我喜欢 Qt5 的功能 API,但我不能将 QObject 作为基础 class 以及我的 API 和实现中的附加 MOC 机制。 Boost signals2 在其连接处理中是线程安全的,但在对连接槽的调用中它不是多线程的(实际上我只是在寻找非阻塞)。

我相信 boost signals2 和 asio 的组合作为事件循环可以满足我的需要,但我不确定如何实现它。另外,我相信其他人也有类似的需求,所以我正在寻找关于如何实现这一点的想法和建议。

谢谢!

boost::signals2::signal 在发出信号的线程上顺序调用槽。如果您希望实现非阻塞行为,您只需自己在不同的线程上发出信号。

据我了解,Qt QueuedConnection 不仅意味着插槽是异步调用的,而且是在接收器特定的线程事件循环上调用的。这不同于在任意线程上调用槽。我不是 100% 清楚你的意图。

假设您不关心槽在哪个线程上被调用,只要它不阻塞,您可以将信号包装在一个小对象中,该对象发布到不同的线程。

一个简单的例子,使用boost::asio:

struct async_signal : std::enable_shared_from_this<async_signal>
{
    boost::signals2::signal<void(void)> signal;
    boost::asio::io_context             executor;

    void emit_async()
    {
        boost::asio::post(excutor, [self_weak = weak_from_this()]()
            {
               if (auto self = self_weak.lock())
               {
                  signal();
               }
            });
    }
}

现在,槽将在调用 io_context::run() 的任何线程上按顺序调用。这通常是某种线程池,例如 boost::asio::thread_pool;

如果您想了解 std::enable_shared_from_this 部分,这是针对 thread safety

您当然可以将此 class 模板化并封装好,但我认为这样更容易理解。