如何释放一个通过istream阻塞的线程

时间:2010-10-21 20:02:21

标签: c++ istream

我创建了两个类。一个用于输入读取(通过istream对象)和解析,另一个用于处理解析器的输出 每个都有一个实例 我让解析器在循环中运行,调用istream :: get(),然后根据输入为第二个对象创建命令。然后将这些命令放在队列中,第二个对象在一个单独的线程中进行处理 现在很明显,我最终需要能够发送“退出”命令。这里出现了问题:“Quit”命令也需要结束解析循环,但我找不到一种方法来通知解析器它应该退出,因为它是在istream :: get()中捕获的。
我需要一种方法从该方法中唤醒它,但我找不到任何...
我曾想过通过从istream :: rdbuf()创建一个ostream对象,给istream对象(在本例中是cin)编写某种“终止序列”。但这不起作用 - 在尝试写入缓冲区后设置badbit 在StackOverflow的另一个问题中,我看到了提到的Boost库的asio类,但我宁愿不依赖第三方库。
有没有办法从istream :: get()唤醒线程 - 即有没有办法从程序内写入istream缓冲区(可能假设它实际上是cin)?
另一种方法是杀死我可以接受的线程,因为在那个特定的地方不需要清理。但是怎么做呢? (我依赖于POSIX线程实现)

2 个答案:

答案 0 :(得分:1)

这有可能在.NET中实现吗? - 如果是这样的话,请看Reactive Framework。 它提供了一种非常优雅的方式来处理,特别是取消它们。 - 除此之外,你还可以获得一个非常可扩展的Linq扩展库,用于各种各样的东西,比如Buffering,Memoization,Zip等。

我们经常使用它来转换(和解析)流数据的建模。

来自Reative团队的Jeff有一些很好的关于Streaming and Reative here的博客:

答案 1 :(得分:1)

您必须依赖标准iostream类之外的其他内容,因为它们不提供select()样式行为。

此外,使用POSIX(在Windows中彻底破坏)无法终止线程。您可以通过pthread_cancel()发出取消请求,但在您的情况下,它可能会停留在不可取消的系统调用中。您特别感兴趣的是read()可能会或可能不会被取消,具体取决于环境。 At least one environment表示取消点可能发生在read(),但不可否认,它是一个Windows POSIX层。此外,Mac OS X(最近为Leopard 10.5.1)在取消性方面实施了read()

一旦遇到这个障碍,你还必须考虑C ++析构函数和pthread_cancel之间的uneasy relationship。并非所有环境都保证将调用析构函数,因此在C ++代码中使用pthread_cancel时必须非常小心。

简而言之,对于可中断的I / O,使用低级I / O和select():一个用于I / O的fd,另一个用于信令的fd(由pipe()创建)。或者,如果你很勇敢,请使用AIO,但最好使用Boost.Asio等高级界面。