【问题标题】:Is std::iostream non-blocking?std::iostream 是非阻塞的吗?
【发布时间】:2018-02-09 21:27:23
【问题描述】:

根据 Boost.Iostreams 的 boost 参考(在第 3.6 节中,在最底部):

http://www.boost.org/doc/libs/1_64_0/libs/iostreams/doc/index.html

尽管 Boost.Iostreams 过滤器和设备概念可以 适应非阻塞 i/o、C++ 标准库流和 流缓冲区接口不能,因为它们缺乏一种方法 区分临时和永久故障以满足读取 或者写请求

但是,函数std::istream::readsome 似乎是非阻塞的,因为可用字符将立即返回,无需阻塞(RAM 副本除外)等待。我的理解是:

std::istream::read 将阻塞直到eof 或读取的字符数。

std::istream::readsome 将立即返回从内部缓冲区复制的字符。

【问题讨论】:

  • readsome() 并没有做你认为它做的事情。它所做的只是返回已经在内部缓冲但尚未读取的字符。
  • 我认为它就是这样做的(也许我的困惑在别处?)。当然这可以被视为非阻塞,而不是等到字符变得可以读取?我会在上面澄清我的理解......
  • 来自 cppreference:“这个函数的行为是高度特定于实现的。”
  • @NeilButterworth 我刚刚阅读了本节并将其理解为高度依赖于它将返回多少数据的实现,但它会立即返回
  • 我可能是错的,但我的理解是“他们缺乏 [..] 来满足读取或写入请求的手段”和非阻塞 readsome 都是正确的,但有没有矛盾,因为readsome 没有发出读请求

标签: c++ iostream


【解决方案1】:

我同意你的观点,readsome 不是阻塞操作。然而,正如指定的那样,它完全不足以作为执行通常称为“非阻塞 I/O”的接口。

首先,不能保证readsome永远返回新数据,即使它可用。因此,为了保证您真正取得进展,您最终必须使用其中一个阻塞接口。

第二,没有办法知道readsome什么时候返回数据。无法“轮询”流,或获取“通知”或“事件”或“回调”。一个可用的非阻塞接口至少需要其中之一。

简而言之,readsome 似乎是为 I/O 流提供非阻塞接口的半生不熟且未指定的尝试。但我从未见过它在生产代码中使用过,我也不希望这样做。

我认为 Boost 文档夸大了这个论点,因为正如您所观察到的,readsome 肯定能够区分临时故障和永久故障。但由于上述原因,他们的结论仍然是正确的。

【讨论】:

  • 是的,我同意这不是一个理想的界面。我的代码使用截止日期计时器调用 readsome 直到 eof 异常。你会建议什么作为替代方案?我必须将流传递给套接字接口。
  • @PeterBingham:当然,或者只是触发一个线程并使用阻塞操作。但这些都与这个问题或我的回答没有太大关系。
【解决方案2】:

在研究非阻塞可移植性时,我在 C++ 标准库中没有发现任何看起来像你认为的那样的东西。

如果您的目标是可移植性,我的解释是最重要的部分是:

http://en.cppreference.com/w/cpp/io/basic_istream/readsome

例如,当与 std::ifstream 一起使用时,某些库 实现用数据填充底层文件缓冲区 文件被打开(并且 readsome() 在这样的实现上读取数据, 可能但不一定是整个文件),而其他 实现仅在实际输入操作时从文件中读取 文件打开后发出的请求(和 readsome() 从不提取任何 字符)。

这表示允许使用 iostream 接口的不同实现懒惰地完成它们的工作,而 readsome() 甚至不能保证工作会被启动。

但是,我认为您对 readsome 保证不会阻塞的解释是正确的。

【讨论】:

  • 我认为您删除了引用的重要部分“例如,当与 std::ifstream 一起使用时,一些库实现会在打开文件后立即用数据填充底层 filebuf ...”我将此理解为readsome 从未真正读取数据,但ifstream 可能在打开文件时已经读取数据,然后才能从readsome 返回
  • 我正在使用 boost::asio。我的 asio 项目中的一个 API 需要一个 iostream,但为了非阻塞,我只想读取可用的内容。
  • @tobi303 很公平,添加了它,以及参考资料的链接
  • 对不起,现在我真的很想理解它.... cppref 还说“提取到立即可用的字符...”,我读为:readsome 保证永远不会“启动”任何acutaly 阅读,但实际上是非阻塞的(但对于从流中进行非阻塞读取实际上仍然无用)
  • @PeterBingham 错误,现在我很困惑。如果您已经定义了一个完全自定义的 iostream 实现,那么它当然可以是非阻塞的?您的问题暗示(至少在我看来)您通常对 iostream 的行为感兴趣。无论如何,我编辑了答案以澄清我认为 readsome 不会阻塞,基于它的读取方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2015-11-06
  • 2012-11-13
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多