472,807 Members | 1,834 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,807 software developers and data experts.

block on reading a half-filled buffer for ifstream

Hi all. I'm using ifstream to read from a named pipe but
i've encountered an annoying problem. For some reason, the
program blocks on reading an ifstream's internal buffer that's
only half-filled. Only when the buffer becomes full does
it resume execution.

Here's my test code for reading from a pipe:
//(compiled with g++ -std=c++98)
//---------------------------------------------
#include <iostream>
#include <fstream>
using namespace std;

const int BUFF_SIZE = 20;

int main()
{
char buffer[BUFF_SIZE+1];
std::ifstream fin("npipe");

std::streambuf * pbuf;
pbuf = fin.rdbuf();
pbuf->pubsetbuf(buffer,BUFF_SIZE);

char c[200];
while(1){

if(pbuf->in_avail() > 0) {
cout << "stuff in buffer: " << pbuf->in_avail() << endl;

fin >> c; //program blocks HERE if buffer not full

cout << "read in stuff : " << c << endl;
cout << "---------------------------" << endl;
}
else
usleep(500000);
}
fin.close();
}
//---------------------------------------------

And for writing to the pipe, i just use:

cat > npipe

on the terminal.

So when i type something down the pipe and hit the return key,
the program does immediately recognise that there's data
available (cos pbuf->in_avail() immediately becomes > 0).

But when i try to read in the data with >> operator, it blocks if
the data being sent does not completely fill up the buffer. So
in the above case, the program blocks until BUFF_SIZE chars have
been sent down the pipe.

incidentally, i tried other read functions in place of >>
but it yield the same result.

//fin.read(c,pbuf->in_avail()); //none of these work either
//fin.readsome(c, 1);
//char test= pbuf->sbumpc();
It is unlikely that it's a pipe problem because i've written
a separate program that uses the C's FILE pointer for reading
where I don't encounter this problem at all.

My question is: doesn't in_avail() specify the number of
characters that are collected and can be read from ifstream's buffer
without blocking? Is there any way i can read a
half-filled streambuf without it blocking on me? Or have i
misunderstood the concept of in_avail() + the readability of
a buffer here?

As a temporary make-do solution, i've set pubsetbuf(buffer,1);
so that whenever a char is received the buffer becomes full, which
kinda resembles an unbuffered stream. (and yes, i've tried
pubsetbuf(0,0) & it doesnt' work. see earlier post on this by
someone else.
http://groups.google.co.nz/groups?hl....de%26rnum%3D1
)

It would be nice if there's a way where i can set streambuf's
buffer size to something > 1 & still be able to read from
the half filled buffer without blocking.

Any suggestions? :)

Thanks heaps in advance,
Des
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 23 '05 #1
1 6131
in********@yahoo.com wrote:
std::ifstream fin("npipe");
std::streambuf * pbuf;
pbuf = fin.rdbuf(); while(1){
if(pbuf->in_avail() > 0) {
Whether this condition ever yields true is actually not
specified. Assuming that the file buffer implemetnation
merely does what the standard requires it returns the number
of characters in the input buffer, i.e. the number if knows
are present before blocking: this is what 'in_avail()' is
supposed to return. Since no character was read, no attempt
is made to read a character by 'in_avail()' since this could
block. If an implementation ever yields something different
from 'in_avail()' than '0' prior to the first read, you are
already relying on behavior which is not required by the
standard!
fin >> c; //program blocks HERE if buffer not full
If this block even though 'in_avail()' returned a value bigger
than zero, it has a very simple reason: the input of the
string only terminates when it detects a space character or
when it detect end of file. Whether there is a space in
currently available buffer or not is not told by 'in_avail()'.
.... and the end of the internal buffer does not count as EOF.
Thus, I'm actually a little puzzled why a buffer size of one
character should solve the problem. I would rather guess that
this assures that the newline on which "cat" sents its internal
buffer reaches the file buffer's buffer and allows the input
of string to terminate.

BTW, if you use the formatted input inserter for character
arrays you should setup a width for the stream to have a point
where input terminates prior to a buffer overrun: if you
receive a sequence of non-spaces which longer than the size of
your buffer, you get a buffer overrun. Probably, you should
better use input to a 'std::string' anyway: this does not have
this error prone feature. If you insist in using a character
array, use it like this:

std::size_t const size = 20;
char buf[size];
fin >> std::setw(size) >> buf;

It is safe to use the same size as the size of the buffer with
'std::setw()' because the stream will only read 'width() - 1'
characters and use the remaining character for a terminating
zero.
My question is: doesn't in_avail() specify the number of
characters that are collected and can be read from ifstream's buffer
without blocking?
No. It does something related: it specifies the number of
characters known to be available. It may return a smaller
number. The default implementation is to return the number of
characters in the stream buffer's buffer. If no character is
read, it is likely to return 0.
Is there any way i can read a half-filled streambuf without
it blocking on me?
Yes but it is not covered by the C++ standard: the standard has
no concept of non-blocking input. You would need to set your
stream to non-blocking using an environment specific approach,
e.g. fcntl(2), to allow non-blocking input. This might mean
that you need to create a simple file stream (it's easy: it is
just 10 lines of code) because you cannot assume that you can
fiddle with a file buffers file descriptor.
Or have i misunderstood the concept of in_avail() + the
readability of a buffer here?


I think you did. You also misunderstood how formatted input is
working.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 23 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Daniel Déchelotte | last post by:
Hi, This is actually two questions in one: how to have a block just fit the data it contains (see my "table-cell" kludge) and how to have it centered in a larger block? My idea is to have my...
20
by: ishmael4 | last post by:
hello everyone! i have a problem with reading from binary file. i was googling and searching, but i just cant understand, why isnt this code working. i could use any help. here's the source code:...
40
by: Kevin Yu | last post by:
is it a bad programming design to throw exception in the try block then catch it??
3
by: Alex Clark | last post by:
Hi All, I'm having some problems reading a network stream. I'm writing a lightweight POP client to handle a very specific task, but I keep unexpectedly reaching the end of the datastream when...
2
by: ruben | last post by:
Hi: After upgrading 7.4.2 to 7.4.5 quite smoothly in a Red Hat 8.0 box, we are having intermitent issues with certain online PHP transactions, returning this error: "Warning: pg_exec() query...
2
by: Jake Barnes | last post by:
Using javascript closures to create singletons to ensure the survival of a reference to an HTML block when removeChild() may remove the last reference to the block and thus destory the block is...
26
by: Bill Norton | last post by:
If you wrap one division around another like this: <div id="wrapper"> <div id="child">...</div> </div> ....the wrapper division will be considered the containing block of the child division...
10
by: Curious | last post by:
Hi, I've found that if I wrap my code with a try-catch block in the fashion illustrated below, it'll do what is specified in the catch section instead of crashing. Could anyone confirm that this...
2
by: cmdolcet69 | last post by:
How can i just parse out the Indicator Readings in a text file so that i can fill an arraylist with the indicator values -------------------Indicator Test RAW BIT Values-------------------...
8
by: Patrick | last post by:
Hello, I'm trying to align a text vertically in a link displayed as a block. But the text is always at top. Is there a solution? Your advices are welcome. Here is a test page: <html>
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.