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.
| [reply] |
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 | [reply] [d/l] |
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";
}
}
}
| [reply] [d/l] |