| What does istream::sync()? [message #17345] |
Sat, 06 October 2007 07:58  |
john[1] Messages: 46 Registered: September 2007 |
Member |
|
|
I am reading TC++PL3 and on page 644 it is mentioned:
"Flushing an istream is done using sync(). This cannot always be done
right. For some kinds of streams, we would have to reread characters
from the real source - and that is not always possible or desirable.
Consequently, sync() returns 0 if it succeeded. If it failed, it sets
ios_base::badbit (21.3.3) and returns -1. Again, setting badbit might
trigger an exception (21.3.6). A sync() on a buffer attached to an
ostream flushes the buffer to output".
So, what exactly should we expect from an call of sync() on an istream?
Making its streambuf to lose all its contents?
The code:
#include <iostream>
int main()
{
using namespace std;
char c;
cin>> c;
cout<< c<< endl;
int sync_failure= cin.sync();
cout<< sync_failure<< endl;
cin >> c;
cout<< c<< endl;
}
in my system produces:
[john@localhost src]$ ./foobar-cpp
test
t
0
e
[john@localhost src]$
|
|
|
| Re: What does istream::sync()? [message #17367 is a reply to message #17345 ] |
Sat, 06 October 2007 16:42   |
Gianni Mariani Messages: 153 Registered: July 2007 |
Senior Member |
|
|
john wrote:
....
> So, what exactly should we expect from an call of sync() on an istream?
> Making its streambuf to lose all its contents?
....
istream is allowed to buffer input. If it does so, it will not be able
to see changes to the parts of the file in it's input buffer after the
buffer is filled. What sync appears to do is to expire the content of
the buffer if the input is appropriate (i.e. file based input).
Below is an strace of your code with the source as input. Notice that
it reads the file into memory and after the sync it reads it again but
offset by 1. If after the first read the file had changed, then the
second read would expose the new contents of the file.
read(0, "#include <iostream>\n\n\nint main()"..., 4096) = 241
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
write(1, "#\n", 2#) = 2
lseek(0, -240, SEEK_CUR) = 1
write(1, "0\n", 20) = 2
read(0, "include <iostream>\n\n\nint main()\n"..., 4096) = 240
write(1, "i\n", 2i) = 2
exit_group(0) = ?
|
|
|
| Re: What does istream::sync()? [message #17385 is a reply to message #17345 ] |
Sun, 07 October 2007 05:48   |
James Kanze Messages: 598 Registered: July 2007 |
Senior Member |
|
|
On Oct 6, 1:58 pm, john <j...@no.spam> wrote:
> I am reading TC++PL3 and on page 644 it is mentioned:
> "Flushing an istream is done using sync(). This cannot always be done
> right. For some kinds of streams, we would have to reread characters
> from the real source - and that is not always possible or desirable.
> Consequently, sync() returns 0 if it succeeded. If it failed, it sets
> ios_base::badbit (21.3.3) and returns -1. Again, setting badbit might
> trigger an exception (21.3.6). A sync() on a buffer attached to an
> ostream flushes the buffer to output".
> So, what exactly should we expect from an call of sync() on an istream?
Nothing. The standard leaves it entirely up to the
implementation; different implementations do different things.
> Making its streambuf to lose all its contents?
Well, it certainly depends on the type of the streambuf; for a
stringbuf, for example, sync is always a no-op. For a file buf,
sync() on input isn't specified by the standard.
Some implementations, I think, simply throw out any data they
happen to have in the buffer. *IF* the implementation is line
buffering the file (as do Unix, and I think Windows, when the
data source is a keyboard), this has more or less the same
effect as ignoring input up to and including the next newline.
Don't use it for this, however, since it will fail if the input
is not line buffered (not from the keyboard). And of course,
it's not standard; other implementations (e.g. g++) simply treat
the sync as a no-op.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
|
| Re: What does istream::sync()? [message #17386 is a reply to message #17367 ] |
Sun, 07 October 2007 05:53   |
James Kanze Messages: 598 Registered: July 2007 |
Senior Member |
|
|
On Oct 6, 10:42 pm, Gianni Mariani <gi3nos...@mariani.ws> wrote:
> john wrote:
> ...> So, what exactly should we expect from an call of sync() on an istream?
> > Making its streambuf to lose all its contents?
> ...
> istream is allowed to buffer input. If it does so, it will not be able
> to see changes to the parts of the file in it's input buffer after the
> buffer is filled. What sync appears to do is to expire the content of
> the buffer if the input is appropriate (i.e. file based input).
That would be logical, wouldn't it. The standard simply says:
"If a get area exists, the effect is implementation defined."
So basically, you can't count on anything. (Practically, of
course, what is "appropriate" for a filebuf, which may be
connected to a tty, a file or even maybe a pipe.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|
|
|
|
|
| Re: What does istream::sync()? [message #17411 is a reply to message #17407 ] |
Sun, 07 October 2007 17:34  |
Gianni Mariani Messages: 153 Registered: July 2007 |
Senior Member |
|
|
john wrote:
> James Kanze wrote:
>>
>> other implementations (e.g. g++) simply treat
>> the sync as a no-op.
>
>
> I am not sure what you mean by this. I am using g++ under Linux and it
> doesn't complain for "cin.sync()".
I'm not sure either since the strace I showed earlier is from a Linux
system. However don't expect your compiler to complain if somthing is
implemented as a no-op.
|
|
|