1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
# $Id: Timer.pm,v 1.1.1.1 2002/03/05 16:34:19 dgl Exp $
=head1 NAME
Timer.pm
=head1 EXAMPLES
use Timer;
$timer = Timer->new;
$timer->addonce(code => \&somesub, data => 'moo', interval => 10);
sub somesub { print shift }
$timer->add(code => sub {
my($timer,$data) = @_;
print "Called $timer->{id} with $data\n";
}, data => 'oink', interval => 1, count => 10);
# Obviously fit $timer->run into how your program needs to use it.
sleep 1;
sleep 1 while $timer->run;
=head1 METHODS
=head2 add
add( code => \&codref, # \&code, sub { print blah..} etc..
data => 'data', # This data is passed back to the coderef when run
interval => num, # Time between being run..
count => [num | undef ], # number of times to run, undef == forever
);
=head2 addonce
Wrapper to add, option count is already set to 1
=head2 addforever
Wrapper to add, option count is set to undef
=head2 delete
delete($id);
=head2 get
returns anon hash specified by $id
=head2 run
checks for timers that need running, returns number actually run.
=head2 call
used internally by run to call an timer when it needs running
=head2 exists
returns true if the timer exists
=cut
package Timer;
use strict;
sub new {
my $class = shift;
# notice it's an array, not a hash
return bless [], $class;
}
sub add {
my($self,%timer) = @_;
my $id = $self->_newid;
$$self[$id] =
{
code => $timer{code},
data => $timer{data},
interval => $timer{interval},
nextexec => $timer{interval} + time,
count => $timer{count} || undef,
'package' => (caller)[0],
id => $id
};
return $id;
}
sub remove_package {
my($self, $package) = @_;
for my $id(0 .. $#$self) {
next unless ref($$self[$id]) eq 'HASH';
if($$self[$id]->{package} eq $package) {
splice(@$self, $id, 1);
}
}
}
# Finds the next free id (element) in the array
sub _newid {
my $self = shift;
for my $id(0 .. $#$self) {
return $id unless ref($$self[$id]) eq 'HASH';
}
return scalar @$self;
}
sub addonce {
my($self,%timer) = @_;
$self->add(%timer,count => 1);
}
sub addforever {
my($self,%timer) = @_;
$self->add(%timer,count => undef);
}
sub delete {
my($self,$id) = @_;
return 0 unless $self->exists($id);
$$self[$id] = undef;
}
sub get {
my($self,$id) = @_;
return $$self[$id];
}
sub run {
my $self = shift;
my $time = time;
my $num = 0;
for my $id(0 .. $#$self) {
next unless ref($$self[$id]) eq 'HASH';
if($time >= $$self[$id]->{nextexec}) {
$self->call($id);
$num++;
}
}
return $num;
}
sub call {
my($self,$id) = @_;
my $timer = $self->get($id);
$timer->{count}-- if defined $timer->{count};
$timer->{nextexec} = $timer->{interval} + time;
# TODO: Make $timer into an object so things like $timer->delete work within
# the timer.
$timer->{code}->($timer,$timer->{data});
if(defined $timer->{count} && $timer->{count} <= 0) {
$self->delete($id);
return 0;
}
1;
}
sub exists {
my($self,$id) = @_;
return 1 if ref($$self[$id]) eq 'HASH';
0;
}
1;
|