Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am curious about writing a script that performs a series of functions in a simple loop that will take sometime to complete. I was wondering if there is a way to say hit the space bar and get the current count of how many times the loop had been traversed?

For example:

#!/usr/bin/perl -w use strict; my $cnt = 0; while ($cnt < 9e27){ # some code here to recognize # a space bar had been hit and # print current value of $cnt. $cnt++; }

Replies are listed 'Best First'.
Re: Report current results during batch process?
by Fletch (Bishop) on Jul 27, 2004 at 17:57 UTC

    Use Term::ReadKey to perform a non-blocking read each time through your loop (after setting for cbreak and noecho). If there's been a key hit, print your status report; if not just keep going.

Re: Report current results during batch process?
by bgreenlee (Friar) on Jul 27, 2004 at 20:28 UTC
    Term::ReadKey works great, but if you're in a tight loop, there's no need to check it every time; it will slow you down big time. Take a look at this:
    use Benchmark; use Term::ReadKey; ReadMode cbreak; # make sure we can ctrl-c it timethese(10, { 'read_every' => sub { my $cnt = 0; while ($cnt < 1e5) { print "$cnt\n" if Read +Key(-1); $cnt++ } }, 'read_1000' => sub { my $cnt = 0; while ($cnt < 1e5) { print "$cnt\n" if not +$cnt % 1000 and ReadKey(-1); $cnt++ } } }); ReadMode restore; # Reset tty mode before exiting [brad:foo]$ perl read_test.pl Benchmark: timing 10 iterations of read_1000, read_every... read_1000: 2 wallclock secs ( 1.18 usr + 0.04 sys = 1.22 CPU) @ 8 +.20/s (n=10) read_every: 42 wallclock secs (29.19 usr + 10.88 sys = 40.07 CPU) @ 0 +.25/s (n=10)
    Reading only every 1000 iterations, at least in this test, still catches every keystroke immediately.

    Brad

Re: Report current results during batch process?
by johnnywang (Priest) on Jul 27, 2004 at 20:02 UTC
    You can start a new thread that reads from stdin, and just share the variable $cnt to that thread,
    use strict; use threads; use threads::shared; my $cnt:shared = 0; my $t = threads->new(\&get_input); while(1){ #simulate some task ++$cnt; sleep 2; } $t->join(); sub get_input{ while(1){ my $key = <>; chomp $key; if($key eq " "){ print "$cnt\n"; } } }