#!/usr/bin/perl --
use strict;
use warnings;
{
my $sentinel = expireAfter( 1, 9 );
print "begin ", scalar(gmtime),"\n";
while( $sentinel->() ){
print "loop ", scalar(gmtime),"\n";
}
print "end ", scalar(gmtime),"\n";
}
{
my $sentinel = expireAfter( 1, 5 );
print "begin ", scalar(gmtime),"\n";
while( $sentinel->() ){
print "loop ", scalar(gmtime),"\n";
}
print "end ", scalar(gmtime),"\n";
}
#~ use constant DEBUG => 1 || !!$ENV{PERL_MYAPP_DEBUG};
use constant DEBUG => 0 || !!$ENV{PERL_MYAPP_DEBUG};
=head2 C<<< checkEveryExpireAfter( $every, $after ) >>>
check $every seconds, if it hasn't been $every seconds yet, wait until
+ it has
stop checking $after seconds have elapsed
checkExpire( $every, $after )
intervalExpire( $every, $after )
afterExpire( $every, $expire )
everyUntil( $second, $expire )
breatheUntil( $second, $expire )
=cut
sub expireAfter {
my( $ten, $after ) = @_;
my $lasttime = time;
my $expire = $lasttime + $after;
DEBUG and warn "## eA ## ten($ten)after($after)lasttime($lasttime)
+expire($expire)";
return sub {
my $newtime = time;
my $diff = $newtime - $lasttime;
if( $expire < $newtime ){
DEBUG and warn "## eA ## expired ( $expire < $newtime )";
return !!0;
} elsif( $diff < $ten ){
DEBUG and warn "## eA ## sleep ( $diff < $ten )";
sleep abs( $diff - $ten );
}
$lasttime = time;
if( $expire < $lasttime ){
DEBUG and warn "## eA ## expired ( $expire > $lasttime )";
return !!0;
} else {
DEBUG and warn "## eA ## loop ( $expire > $lasttime )";
return !!1;
}
};
}
sub expireAfterGood {
my( $ten, $after ) = @_;
my $lasttime = time;
my $expire = $lasttime + $after;
return sub {
my $newtime = time;
my $diff = $newtime - $lasttime;
if( $expire < $newtime ){
warn "( $expire < $newtime )";
return !!0;
} elsif( $diff < $ten ){
warn "expired ( $diff < $ten )";
sleep abs( $diff - $ten );
}
$lasttime = time;
if( $expire < $lasttime ){
warn "expired ( $expire > $lasttime )";
return !!0;
} else {
return !!1;
}
};
}
sub expireAfterBuggy {
my( $ten, $after ) = @_;
my $lasttime = time;
my $expire = $lasttime + $after;
return sub {
my $newtime = time;
my $diff = $newtime - $lasttime;
if( $expire > $lasttime ){
warn "( $expire > $lasttime )";
return !!0;
} elsif( $diff < $ten ){
warn "expired ( $diff < $ten )";
sleep abs( $diff - $ten );
}
$lasttime = time;
if( $expire > $lasttime ){
warn "expired ( $expire > $lasttime )";
return !!0;
} else {
return !!1;
}
};
}
I started with expireAfterBuggy, tweaked it until it did the right thing, and then called it expireAfterGood, then improved the diagnostics, added documentation, tried to come up with a better name (this part needs work )
It is also possible to write it so that this does the right thing while( nameHere( 'timername', 10, 3600 ) ){ ... }
but it could "leak" memory if not used in a loop like that
Important thing, instead of while( ( sleepy $time) and $time + 300 < $expiry )
have while( oneThing($time, $expiry, 300) )
oneThing can have a sleepy and whatever else you need to make oneThing easier to understand ;) but since they both share $time and its simple scalar, stick it together under oneName |