How to block on reading a c++ stringstream to wait

2019-06-28 04:37发布

问题:

So, I've been trying to figure out, how to wait for data from a C++ stringstream (for instance), without being constantly checking if data is there, which is quite CPU consuming.

I'm perfectly able to read, for instance, from a serial device, and lock the process while no data arrives, but unfortunately I haven't been able to figure how to do that with C++ streams.

I'm sure I'm missing something, since cin does exactly that, i.e., waits for the return key to step out from istream reading, but how does it do it?

Thanks in advance for any light on the subject.

回答1:

Streams obtain data from an std::streambuf. For the case of std::cin it calls the system's read() function (or equivalent) which blocks until data is handed over from the operating system. The console normally sends complete lines. String streams have no concept of getting new data, i.e., they would fail when having reached the end of the current data. There isn't a concept of blocking.

You didn't quite say what you are doing but from the sounds of it try to communicate data between two threads: one reading and possibly blocking until data is available and one filling in more data. You could create a corresponding stream buffer quite easily: std::streambuf::underflow() would wait() on a condition variable if there is no data. std::streambuf::overflow() would set up the buffer appropriately and signal the condition variable. Obviously, there is some need of synchronization necessary. Most of the reading and writing isn't doing any synchronization, though. This effectively means that you will need two separate buffers for input and output and need to copy the data in std::streambuf::underflow().



回答2:

You can't. The only way std::stringstream can know that there isn't any further data is that there isn't any data in the stream.

It's an interesting thought, however. << on an std::stringstream only returns true if the write side has been closed. The only problem with the idea is that std::stringstream doesn't have any idea of open or closed.

The real question, however, is what you're trying to achieve. std::stringstream operates in process, and in that case, there's really no need for formatting (which is the abstraction of the iostreams in general). Just stuff the raw objects in an std::deque. The only time you should need to worry about formatting is when communicating with the exterior. std::istringstream is very useful, for example, when you're getting the string from std::getline on a file, or from some other source. Similarly, std::ostringstream is useful when formatting data for some external source which requires a string of some sort. But I've never found a use for std::stringstream; it's there more for reasons of orthogonality, I think.