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