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

发布于 2024-09-28 19:54:55 字数 602 浏览 0 评论 0原文

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

i have created two classes. One for input reading (through an istream object) and parsing and the other one for processing the output of the parser.
There is one instance of each of those.
I have the parser running in a loop calling istream::get() and then creating commands for the second object based upon the input. These commands are then put on a queue which the second object processes in a separate thread.
Now it is quite obvious that I eventually need to be able to send a "Quit" command. Here the problem arises though: The "Quit" command needs to end the parsing loop as well but I can't find a way to signal the parser that it should quit because it is caught within istream::get().
I would need a way to wake it from that method, but I cannot find any...
I have thought of writing some sort of "termination sequence" to the istream object (which in this case is cin) by creating an ostream object from istream::rdbuf(). But that doesn't work - The badbit is set after the attempt to write to the buffer.
In another question at StackOverflow I saw the asio class of the Boost library mentioned, but I'd rather not depend on third party libraries.
Is there a way to wake the thread from istream::get() - i.e. is there a way to write to the istream buffer (maybe assuming it actually is cin) from within the program?
Another approach would be to kill the thread which I could find acceptable as well since there is no cleanup needed in that specific place. But how can this be done? (I'm relying on a POSIX thread implementation)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

永不分离 2024-10-05 19:54:55

您将不得不依赖于标准 iostream 类以外的其他东西,因为它们不提供 select() 风格的行为。

另外,在 POSIX 中杀死线程是不可能的(在 Windows 中完全被破坏)。您可以通过 pthread_cancel() 发出取消请求,但在您的情况下,它可能会陷入不可取消的系统调用中。您特别感兴趣的是,read() 可能会也可能不会被取消,具体取决于环境。 至少一个环境表明取消点可能 发生在 read() 中,尽管不可否认它是 Windows POSIX 层。另外,Mac OS X,最近为 Leopard 10.5.1,在可取消性方面有一个损坏的 read() 实现。

一旦克服了这个障碍,您还必须考虑 C++ 析构函数和 pthread_cancel 之间的不稳定关系。并非所有环境都保证会调用析构函数,因此在 C++ 代码中使用 pthread_cancel 时必须非常小心。

简而言之,对于可中断 I/O,请使用低级 I/O 和 select():一个 fd 用于 I/O,第二个 fd(由 pipe()) 用于信号发送。或者,如果您足够勇敢,请使用 AIO,但您可能会更好关闭使用高级接口,例如 Boost.Asio

You will have to depend on something other than the standard iostream classes, because they don't provide select()-style behaviour.

Also, killing the thread is impossible with POSIX (and utterly broken in Windows). You can issue a cancellation request via pthread_cancel(), but in your case, it may be stuck in an un-cancellable system call. Of particular interest to you, read() may or may not be cancellable, depending on the environment. At least one environment says that a cancellation point may occur in read(), though admittedly it is a Windows POSIX layer. Also, Mac OS X, as recently as Leopard 10.5.1, had a broken read() implementation with respect to cancellability.

Once past this hurdle, you also have to consider the uneasy relationship between C++ destructors and pthread_cancel. Not all environments guarantee that destructors will be called, so you have to be extremely cautions when using pthread_cancel in C++ code.

In short, for interruptible I/O, use low-level I/O and select(): one fd for I/O, a second fd (created by pipe()) for signalling. Or, if you're brave, use AIO, but you're probably better off using a high level interface such as Boost.Asio.

三生池水覆流年 2024-10-05 19:54:55

这有可能在 .NET 中实现吗? - 如果是这样,请查看响应式框架
它提供了一种非常优雅的方式来处理,尤其是动态取消流。

  • 除此之外,您还可以获得一个非常可扩展的 Linq 扩展库,适用于各种内容,例如缓冲、记忆、Zip 等。

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

Reative 团队的 Jeff 有一些关于 此处的流式传输和响应式

Any chance this is implemented in .NET? - if so take a look at the Reactive Framework.
It provides a very elegant way of handling streams and especially cancelling them on the fly.

  • On top of this, you get a very extensible library of Linq extension for all sorts of stuff, like Buffering, Memoization, Zip ect..

We use it a lot for transforming (and parsing), modelling of streamed data.

Jeff from the Reative team has a couble of nice blogs about Streaming and Reative here:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文