Kyle R . Burton on Mon, 24 Jun 2002 15:30:14 +0200 |
> I'm writing a c++ app to read a command stream from a fifo. Commands > are delimited by newlines. The app must be able to process other tasks > (running in a while loop) if there is no data incoming from the fifo. > Right now, I'm using ifstream's rdbuf()->fd() to get the file descriptor > so I can use poll() on the fifo. When there is a read event, I do an > ifstream::getline() on the input stream class. The problem occurs when > the sending program sends two lines at once, i.e. before the listener > task is run again. The getline() is only called once for each poll() > that returns positive, however sometimes really two or more getline()s > are needed. I would have thought that checking for the POLLIN event > would have returned true since there were more data left to read. > However, my guess is that the ifstream class has an internal buffer > which has the next command inside, so the poll() returns false. > > Any ideas? Right now I'm looking at setting O_NDELAY on the file > descriptor. This would certainly allow a simple read() function to work > on it, but would the getline() work correctly? I'm not sure you can do what you want with getline(), since it will block untill it finds the next newline - there are 2 ways I can think of to solve this. The first is to use threads, have a 'getline' thread and have your other thread do the work. The second is to fall back to stdio functions and make your main loop something like: char *buff; // and allocate some space... int numBytes; while(1) { if( poll() ) { numBytes = fillBuffer(); if( 0 == numBytes ) { handleReadError(); break; } } while( aLineIsAvailableInTheBuffer() ) { // look for a "\n" char* line = removeLineFromBuffer(); dispatch( line ); } } Of course, there is alot left to fill in. You'll have to check for buffer length in fillBuffer() and extend it if the input line is larger than the buffer. All fillBuffer has to do is append to the end of the buffer, returning the number of bytes read -- if 0 bytes are read when poll() returned a status indicating that data was ready, then there is probably some kind of error on the file descriptor. removeLineFromBuffer() will have to lop off the first line, and left shift the rest of the data in the buffer. If there was more than 1 line available to be read, the inner while() loop will process them all. This is only one way to solve the problem...you might want to stress interactivity (reading the lines) over the processing, in which case you'd probably want to check for data to read more often, or not process all available lines while there is data to read...a bit more complex, but that can be worked out. HTH Kyle -- ------------------------------------------------------------------------------ Wisdom and Compassion are inseparable. -- Christmas Humphreys mortis@voicenet.com http://www.voicenet.com/~mortis ------------------------------------------------------------------------------ ______________________________________________________________________ Philadelphia Linux Users Group - http://www.phillylinux.org Announcements-http://lists.phillylinux.org/mail/listinfo/plug-announce General Discussion - http://lists.phillylinux.org/mail/listinfo/plug
|
|