2009-10-19 24 views
4

我已经通过#2类似的问题走了,但仍然不能得到一个很好的答案:信号和Boost库插槽VS多线程

  1. how boost implements signals and slots
  2. How signal and slots are implemented

我对这个信号/插槽是如何实现的相当困惑。 Q1:从以下代码中,sig连接到两个函数(Hello()和World()),并且似乎函数以序列化方式调用,这也意味着一个函数(Hello( ))需要在进入另一个函数(World())之前完成? =>单线程程序

问题二:是否有无法启用多线程信号/槽?(=> World()将立即启动,不需要等待Hello()完成。)或者如果它是不推荐,你介意告诉我为什么?

Sample codes on Boost website

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

输出: 你好,世界!

回答

3

Q1:
这些调用是序列化的。什么样的信号在内部被做了很大的简化:

foreach connection: 
    call handler 

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

Q2:
升压信号1不是线程安全的;信号2是,但仍然有序列化的呼叫。由于信号主要用于事件处理,所以在处理程序中实际上没有做太多工作是很常见的风格。
因此,在并行调用它们时没有真正的好处,好处通常不会证明需要的线程调用的开销。

2

问题1:你说的没错。修复了您引用的my answerthe question以反映这一点。第二季度:看起来你应该对线索感到困惑。在发射/捕获过程中什么包含代码是插槽。因此,如果您想同时运行代码,则应将插槽置于不同的线程中。

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

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