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.
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()
.
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.