5

我在 Stackoverflow 上遇到过类似的问题,但仍然无法得到一个好的答案:

  1. boost如何实现信号和槽
  2. 信号和槽是如何实现的

我对这个信号/槽是如何实现的感到很困惑。

Q1:从下面的代码看,sig连接了两个函数(Hello()和World()),看起来函数是序列化调用的,这也暗示了,一个函数(Hello())需要在进入另一个函数(World())之前完成?=> 单线程程序

Q2:有没有启用多线程信号/槽?(=> World() 会立即启动,不需要等待 Hello() 完成。)或者如果不推荐,你介意告诉我为什么?

Boost 网站上的示例代码

struct Hello 
{
  void operator()() const { std::cout << "Hello";}
};
struct World
{
  void operator()() const { std::cout << ", World!" << std::endl;}
};

boost::signal<void ()> sig;
sig.connect(Hello());
sig.connect(World());
sig();

输出:你好,世界!

4

2 回答 2

4

Q1:
调用是序列化的。信号在内部所做的是,大大简化了:

foreach connection:
  call handler

因此,您不想长时间阻塞处理程序。如果你需要做很多工作,你可以从那里调用它,例如为它创建一个线程。

Q2:
boost 信号 1 甚至不是线程安全的;信号 2 是,但仍然会进行序列化调用。由于信号主要用于事件处理,因此在处理程序中实际上不做太多工作是一种常见的风格。
因此,将它们称为“并行”并没有真正的好处,这些好处通常不能证明必要线程调用的开销是合理的。

于 2009-10-19T23:09:01.393 回答
3

Q1:你是对的。修正了我对您引用的问题的回答以反映这一点。

Q2:您似乎对应该线程化的内容感到困惑。在发射/捕获过程中,包含代码的是插槽。所以如果你想同时运行代码,你应该把放在不同的线程中。

Qt 支持这种行为(实际上不知道 boost),并且在 qt 手册中有一章解释说,对于这种行为,您很可能需要“排队处理”。但是你必须在执行槽代码的线程中拥有“事件循环”的概念(因为你不能只是告诉工作线程“嘿,停止做你的事情,改为这样做!”)。

如果您不想等待,则必须直接在插槽代码中生成线程。而且您不应该忘记在两个插槽都可以访问的代码中使用某种“等待”功能。顺便说一句,boost 和 Qt 都有很好的系统线程库包装器,可以轻松地做到这一点。

于 2009-10-19T23:09:02.517 回答