From: Matt S Trout Date: Thu, 19 Jul 2012 17:55:45 +0000 (+0000) Subject: timer support in MiniLoop X-Git-Tag: v0.002002~7 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=befabdee3a3a75da8dd2fd21a2a6c80d8ed0bcff;p=scpubgit%2FObject-Remote.git timer support in MiniLoop --- diff --git a/Changes b/Changes index 990c11b..e24ef1b 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,5 @@ + - timer support in MiniLoop + 0.002001 - 2012-07-18 - start::, maybe::start:: and next:: - automatic prompting for sudo passwords diff --git a/lib/Object/Remote/MiniLoop.pm b/lib/Object/Remote/MiniLoop.pm index b74619c..de2515f 100644 --- a/lib/Object/Remote/MiniLoop.pm +++ b/lib/Object/Remote/MiniLoop.pm @@ -1,6 +1,7 @@ package Object::Remote::MiniLoop; use IO::Select; +use Time::HiRes qw(time); use Moo; # this is ro because we only actually set it using local in sub run @@ -10,6 +11,8 @@ has is_running => (is => 'ro', clearer => 'stop'); has _read_watches => (is => 'ro', default => sub { {} }); has _read_select => (is => 'ro', default => sub { IO::Select->new }); +has _timers => (is => 'ro', default => sub { [] }); + sub pass_watches_to { my ($self, $new_loop) = @_; foreach my $fh ($self->_read_select->handles) { @@ -36,6 +39,26 @@ sub unwatch_io { $self->_read_select->remove($fh); delete $self->_read_watches->{$fh}; } + return; +} + +sub watch_time { + my ($self, %watch) = @_; + my $at = $watch{at} || do { + die "watch_time requires at or after" unless my $after = $watch{after}; + time() + $after; + }; + die "watch_time requires code" unless my $code = $watch{code}; + my $timers = $self->_timers; + my $new = [ $at => $code ]; + @{$timers} = sort { $a->[0] <=> $b->[0] } @{$timers}, $new; + return "$new"; +} + +sub unwatch_time { + my ($self, $id) = @_; + @$_ = grep !($_ eq $id), @$_ for $self->_timers; + return; } sub loop_once { @@ -48,6 +71,12 @@ sub loop_once { foreach my $fh (@$readable) { $read->{$fh}(); } + my $timers = $self->_timers; + my $now = time(); + while (@$timers and $timers->[0][0] <= $now) { + (shift @$timers)->[1]->(); + } + return; } sub want_run { @@ -58,6 +87,7 @@ sub want_run { sub run_while_wanted { my ($self) = @_; $self->loop_once while $self->{want_running}; + return; } sub want_stop { @@ -71,6 +101,7 @@ sub run { while ($self->is_running) { $self->loop_once; } + return; } 1; diff --git a/t/start_core.t b/t/start_core.t index 3b5aeae..a636e59 100644 --- a/t/start_core.t +++ b/t/start_core.t @@ -83,13 +83,14 @@ is($res, 'S3', 'Asynchronous code ok'); is(S1S->get_s2->get_s3, 'S3', 'Sync without start'); -open my $fh, '<', File::Spec->devnull; - -Object::Remote->current_loop->watch_io( - handle => $fh, - on_read_ready => sub { - $S1F::C->() if defined $S1F::C; - $S2F::C->() if defined $S2F::C; +Object::Remote->current_loop->watch_time( + after => 0.1, + code => sub { + $S1F::C->(); + Object::Remote->current_loop->watch_time( + after => 0.1, + code => sub { $S2F::C->() } + ); } );