I/O buffers

N

Noah Roberts

It was my understanding that doing something like
'cin.rdbuf()->pubsetbuf(NULL, 0)' would cause any buffering troubles to
stop. I am not sure where the problem resides, but I am experiencing
difficulties in this area.

Basically what I am trying to do is an interface/engine setup where the
engine communicates through stdin/out and the interface communicates
with the engine through pipes to these handles. I thought I had it
working correctly until I used a certain library (gnustep) to create an
interface and now I am running into what looks like a buffer issue.

When the interface sends two commands (separated by \n) to the engine
quickly the engine gets the first but then fails to read the second or
following. Later when the same set of commands is sent again the engine
recieves what it had not before and then the first of the current set.
I also tried something like 'cat | engine' and got similar results. Not
sure if cat is buffering or not. I am also unsure in which part the
problem resides, engine or interface.

I shut of cin's buffer with 'cin.rdbuf()->pubsetbuf(NULL,0)' and then
read lines with this code:

while (Interface::readReady())
{
cerr << "Input ready.\n";
string input = Interface::readLine();
if (!CommandDispatcher::interpretAndDispatch(input))
Interface::printRaw(string("Error (unknown command): ") + input
+ "\n");
}


readLine() is:


string final;

int c;
while (cin && (c = cin.get()) != '\n') // Read up to '\n'
final += c;

cerr << "Data Read: *" << final << "*" << endl;

return final;

Of course everything in Interface::readReady() is off-topic and
unfortunately this is what is failing. However, all this function does
is poll stdin (using select()) to see if something is available and
return true if so. I am wondering if the problem is actually elsewhere,
like the above snippets for instance.

Unfortunately I am also getting no responce for the readReady() function
from any on-topic group :p That is why I am really hoping that the
error is somewhere else.

NR
 
T

tom_usenet

It was my understanding that doing something like
'cin.rdbuf()->pubsetbuf(NULL, 0)' would cause any buffering troubles to
stop. I am not sure where the problem resides, but I am experiencing
difficulties in this area.

I think that buffering of stdin might be causing your problems, but it
isn't necessarily the case.
Basically what I am trying to do is an interface/engine setup where the
engine communicates through stdin/out and the interface communicates
with the engine through pipes to these handles. I thought I had it
working correctly until I used a certain library (gnustep) to create an
interface and now I am running into what looks like a buffer issue.

I've been there, done that, ended up rewriting to use shared memory
and native messaging for performance reasons, but don't let that stop
you (I was writing a realtime system). I did get it working before the
rewrite though, so read on...
When the interface sends two commands (separated by \n) to the engine
quickly the engine gets the first but then fails to read the second or
following. Later when the same set of commands is sent again the engine
recieves what it had not before and then the first of the current set.
I also tried something like 'cat | engine' and got similar results. Not
sure if cat is buffering or not. I am also unsure in which part the
problem resides, engine or interface.

I shut of cin's buffer with 'cin.rdbuf()->pubsetbuf(NULL,0)' and then
read lines with this code:

For a start, I'd remove the unbuffering call - the code can be fixed
so that you don't need it.

Have you set stdin to non-blocking? blocking is generally the default,
and might work best for you here (it simplifies the code a bit) if the
writer should be writing whole lines.
while (Interface::readReady())
{
cerr << "Input ready.\n";
string input = Interface::readLine();
if (!CommandDispatcher::interpretAndDispatch(input))
Interface::printRaw(string("Error (unknown command): ") + input
+ "\n");
}


readLine() is:


string final;

int c;
while (cin && (c = cin.get()) != '\n') // Read up to '\n'
final += c;

Replace the above with the briefer and faster:
std::getline(std::cin, final);
cerr << "Data Read: *" << final << "*" << endl;

return final;

Of course everything in Interface::readReady() is off-topic and
unfortunately this is what is failing. However, all this function does
is poll stdin (using select()) to see if something is available and
return true if so. I am wondering if the problem is actually elsewhere,
like the above snippets for instance.

readReady needs to be fixed by adding this to the start:

if (std::cin.in_avail() > 0)
return true;

If std::cin has any characters buffered, return immediately. Hopefully
that will fix your problem.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
N

Noah Roberts

readReady needs to be fixed by adding this to the start:

if (std::cin.in_avail() > 0)
return true;

If std::cin has any characters buffered, return immediately. Hopefully
that will fix your problem.

I will try that again, but last time I did it did not work as expected.
I don't recall which way it went, but in_avail returned the same value
no matter what conditions on certain systems.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top