4

我希望我的程序等待在 FIFO 中读取某些内容,但如果read(我使用std::fstream)持续超过 5 秒,我希望它退出。

有可能还是我必须alarm绝对使用?

谢谢你。

4

2 回答 2

1

我不相信有一种干净的方法可以实现这一点,即仅可移植的 C++ 解决方案。您最好的选择是在基于 *nix 的系统和Windows上使用pollor 。selectWaitForSingleObjectWaitForMultipleObjects

您可以通过创建streambuffer将调用转发到真实streambuffer对象的代理类来透明地执行此操作。这将允许您wait在实际读取之前调用适当的函数。它可能看起来像这样......

class MyStreamBuffer : public std::basic_streambuf<char>
{
public:
    MyStreamBuffer(std::fstream& streamBuffer, int timeoutValue)
        : timeoutValue_(timeoutvalue),
          streamBuffer_(streamBuffer)
    {
    }

protected:
    virtual std::streamsize xsgetn( char_type* s, std::streamsize count )
    {
        if(!wait(timeoutValue_))
        {
            return 0;
        }

        return streamBuffer_.xsgetn(s, count);
     }

private:
     bool wait() const
     {
         // Not entirely complete but you get the idea
         return (WAIT_OBJECT_0 == WaitForSingleObject(...));
     }

    const int       timeoutValue_;
    std::fstream&   streamBuffer_;
};

您需要在每次通话时执行此操作。它可能会有点乏味,但会提供一个透明的解决方案来提供超时,即使在客户端代码中可能没有明确支持它们。

于 2013-04-19T22:35:40.660 回答
0

对于我解决问题的方式感兴趣的人,这是我从流中读取的函数。我最终无法使用std::fstream,因此我将其替换为C系统调用。

std::string
NamedPipe::readForSeconds(int seconds)
{
    fd_set              readfs;
    struct timeval      t = { seconds, 0 };

    FD_ZERO(&readfs);
    FD_SET(this->_stream, &readfs);

    if (select(this->_stream + 1, &readfs, NULL, NULL, &t) < 0)
        throw std::runtime_error("Invalid select");
    if (FD_ISSET(this->_stream, &readfs))
        return this->read();
    throw NamedPipe::timeoutException();
}
于 2013-04-19T23:02:21.343 回答