PDA

View Full Version : Non-blocking stream read



akiross
15th April 2009, 03:21
Hello,
does Qt provide some way for reading something from a stream (qtextstream, associated with stdin/stdout) in a non-blocking fashon?

Here's what i've to do:
my application checks every N msec if new data has arrived - a timer calls readData(). This method should check if there are new data on the stream for reading. If there aren't, just return, else read the data and process them.

I'm not using threads and i'd like to avoid them.
There is some way? (maybe using tell() or something similar?)
I tried with bytesAvailable() but returns always 0...

Thanks!

Edit:
pos() and size() return always 0, isSequential() returns true, but bytesAvailable() is always 0, too.

wysota
15th April 2009, 09:35
No, the actual reading is performed in a synchronous manner. You can use a QSocketNotifier with stdin to get a signal based notification upon data arrival.

akiross
15th April 2009, 17:40
Thanks, it was exactly what I was needing :)
Actually I solved my problem, but there's one more question: how can I know if there are pending data on stdin?

Actually, my parsing function is blocking:

QPoint p;
cin >> p;
Will block if the point isn't complete (it have a syntactic structure like "(x,y)" ).

It would be nice if I could read the partial data as they are notified, put them in a buffer and analyze the buffer with a regex: if full data are present, I can use the parsing function without blocking. The parsed data are consumed and the incomplete data will be added at the next notification (by QSocketNotifier of course).

This would allow me to read data like:


while (buffer.indexOf(regex) != -1) {
QPoint p;
buffer >> p;
}


I was thinking to do this by keeping a QString buffer and QTextStream on it, but there is a problem: if I read all the data from the stream (like readAll()), it will block, because stdin is always open and waiting for new data:



QTextStream input(/* using stdin */);
static QString buffer;
...
void notification(int stream) {
buffer += input.readAll(); // Blocks here
// Check the buffer using QRegex and extract all the available data
}


Do you have any advice on how to do this?

Thanks wysota, you're always helpful! :)

wysota
16th April 2009, 12:07
If you use a socket notifier, you will be notified upon arrival of new data. Then you can use the IODevice you are using or QTextStream to read from stdin to do the actual reading.


QFile stdinfile;
stdinfile.open(0, QFile::ReadOnly);
//...
int pending = stdinfile.bytesAvailable();