Prev: FAQ 8.10 How do I read and write the serial port?
Next: FAQ 4.71 How do I handle binary data correctly?
From: Dilbert on 13 Jan 2010 04:40 On 13 jan, 00:09, "Peter J. Holzer" <hjp-usen...(a)hjp.at> wrote: > On 2010-01-12 22:48, Jim Gibson <jimsgib...(a)gmail.com> wrote: > > > [problem with flushing output to screen before reading input snipped] > > > It is likely that it is the tee program that is doing the buffering and > > needs to be flushed before input is read. > > No. tee doesn't buffer (at least not the implementations I'm familiar > with). I confirm, if I flush STDOUT in my Perl program, then the output is ok. > Dilbert correctly (except that he erroneously calls a pipe a > "flat file", but that makes no difference in this context) the behaviour > required for stdio by the C standard. Apparently perlio emulates this > behaviour. Under normal circumstances, perlio emulates the behaviour required for stdio by the C standard correctly. And I understand that this behaviour is dropped if I re-open STDOUT to another file. What I would like to achieve is to teach perlio *not* to forget this behaviour in this particular case when STDOUT is re-opened to a pipe that tee's back to the terminal.
From: Peter J. Holzer on 13 Jan 2010 07:29 On 2010-01-13 09:40, Dilbert <dilbert1999(a)gmail.com> wrote: > On 13 jan, 00:09, "Peter J. Holzer" <hjp-usen...(a)hjp.at> wrote: >> Dilbert correctly (except that he erroneously calls a pipe a >> "flat file", but that makes no difference in this context) the behaviour >> required for stdio by the C standard. Apparently perlio emulates this >> behaviour. > > Under normal circumstances, perlio emulates the behaviour required for > stdio by the C standard correctly. It also emulates the behaviour correctly in this case. > And I understand that this behaviour is dropped if I re-open STDOUT to > another file. AIUI, you didn't reopen STDOUT. Filedescriptor 1 already referred to a non-terminal when your program was called. > What I would like to achieve is to teach perlio *not* to forget this > behaviour in this particular case when STDOUT is re-opened to a pipe > that tee's back to the terminal. Yes, I understood that. But the behaviour you want is *not* allowed by the C standard. Of course the C standard is only marginally relevant to perl, so perl could implement a more intelligent flushing scheme. However, it cannot detect what the program on the other end of the pipe (tee in this case) does, so it either needs to be a better heuristic (which may be difficult because "better" includes "doesn't break existing programs") or it needs to be user/programmer-controllable. Maybe a function "flush that stream before reading from this stream". Or - even more generic - just a hook which is called for certain ops. So you could do something like $in->add_hook(pre_read => sub { $out->flush }); hp
From: Dilbert on 13 Jan 2010 08:41 On 13 jan, 13:29, "Peter J. Holzer" <hjp-usen...(a)hjp.at> wrote: > Yes, I understood that. But the behaviour you want is *not* allowed by > the C standard. Of course the C standard is only marginally relevant to > perl, so perl could implement a more intelligent flushing scheme. > However, it cannot detect what the program on the other end of the pipe > (tee in this case) does, so it either needs to be a better heuristic > (which may be difficult because "better" includes "doesn't break > existing programs") I agree, detecting what the program on the other end of the pipe does is difficult. > or it needs to be user/programmer-controllable. > Maybe a function "flush that stream before reading from this stream". Or > - even more generic - just a hook which is called for certain ops. Adding a hook which is called for certain ops is the way I want to go. > So you could do something like > > $in->add_hook(pre_read => sub { $out->flush }); Can this hook also be added to a simple my $answer = <STDIN>; Maybe the following ? use IO::Handle; STDIN->add_hook(pre_read => sub { STDOUT->flush }); ....but that gave me an error: Can't locate object method "add_hook" via package "IO::Handle"
From: Peter J. Holzer on 13 Jan 2010 09:45 On 2010-01-13 13:41, Dilbert <dilbert1999(a)gmail.com> wrote: > On 13 jan, 13:29, "Peter J. Holzer" <hjp-usen...(a)hjp.at> wrote: >> Maybe a function "flush that stream before reading from this stream". Or >> - even more generic - just a hook which is called for certain ops. > > Adding a hook which is called for certain ops is the way I want to go. > >> So you could do something like >> >> $in->add_hook(pre_read => sub { $out->flush }); > > Can this hook also be added to a simple > my $answer = <STDIN>; > > Maybe the following ? > use IO::Handle; > STDIN->add_hook(pre_read => sub { STDOUT->flush }); > > ...but that gave me an error: > Can't locate object method "add_hook" via package "IO::Handle" This was an idea how such a feature could look like in a future version of perl. It doesn't currently exist (as far as I know). I think the simplest solution for you is to just set $|. Since you you send the output to the screen anyway, this is unlikely to degrade performance noticeably. hp
From: Ben Morrow on 13 Jan 2010 21:19 Quoth "Peter J. Holzer" <hjp-usenet2(a)hjp.at>: > On 2010-01-13 09:40, Dilbert <dilbert1999(a)gmail.com> wrote: > > > What I would like to achieve is to teach perlio *not* to forget this > > behaviour in this particular case when STDOUT is re-opened to a pipe > > that tee's back to the terminal. > > Yes, I understood that. But the behaviour you want is *not* allowed by > the C standard. Of course the C standard is only marginally relevant to > perl, so perl could implement a more intelligent flushing scheme. > However, it cannot detect what the program on the other end of the pipe > (tee in this case) does, so it either needs to be a better heuristic > (which may be difficult because "better" includes "doesn't break > existing programs") or it needs to be user/programmer-controllable. > Maybe a function "flush that stream before reading from this stream". Or > - even more generic - just a hook which is called for certain ops. So > you could do something like > > $in->add_hook(pre_read => sub { $out->flush }); This is called a 'PerlIO layer'. Writing something like this should be trivial with PerlIO::via, at least once you've worked out how to pass the handle that should be flushed (binmode only accepts a string), and not terribly difficult from XS using the real API. Ben
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: FAQ 8.10 How do I read and write the serial port? Next: FAQ 4.71 How do I handle binary data correctly? |