ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Timer.pm
(Generate patch)

Comparing Coro/Coro/Timer.pm (file contents):
Revision 1.32 by root, Wed Feb 1 23:59:41 2006 UTC vs.
Revision 1.33 by root, Fri Nov 24 15:34:33 2006 UTC

22 22
23=cut 23=cut
24 24
25package Coro::Timer; 25package Coro::Timer;
26 26
27BEGIN { eval { require warnings } && warnings->unimport ("uninitialized") } 27no warnings;
28 28
29use Carp (); 29use Carp ();
30use Exporter; 30use Exporter;
31 31
32use Coro (); 32use Coro ();
33use AnyEvent ();
33 34
34BEGIN {
35 eval "use Time::HiRes 'time'";
36}
37
38$VERSION = 1.9; 35$VERSION = "2.0";
39@EXPORT_OK = qw(timeout sleep); 36@EXPORT_OK = qw(timeout sleep);
40 37
41=item $flag = timeout $seconds; 38=item $flag = timeout $seconds;
42 39
43This function will wake up the current coroutine after $seconds 40This function will wake up the current coroutine after $seconds
57 54
58=cut 55=cut
59 56
60# deep magic, expecially the double indirection :(:( 57# deep magic, expecially the double indirection :(:(
61sub timeout($) { 58sub timeout($) {
62 my $self = \\my $timer;
63 my $current = $Coro::current; 59 my $current = $Coro::current;
64 $timer = _new_timer(time + $_[0], sub { 60 my $timeout;
65 undef $timer; # set flag 61 bless {
62 timer => AnyEvent->timer (after => $_[0], cb => sub {
63 $timeout = 1;
66 $current->ready; 64 $current->ready;
67 }); 65 }),
68 bless $self, 'Coro::timeout'; # weird quoting required by 5.9.3, it seems 66 timeout => \$timeout,
67 }, "Coro::Timer::Timeout";
69} 68}
70 69
71package Coro::timeout; 70package Coro::Timer::Timeout;
72 71
73sub bool { 72sub bool { ${$_[0]{timeout}} }
74 !${${$_[0]}}
75}
76
77sub DESTROY {
78 ${${$_[0]}}->cancel if ${${$_[0]}};
79 undef ${${$_[0]}}; # without this it leaks like hell. breaks the circular reference inside the closure
80}
81 73
82use overload 'bool' => \&bool, '0+' => \&bool; 74use overload 'bool' => \&bool, '0+' => \&bool;
83 75
84package Coro::Timer; 76package Coro::Timer;
85 77
90 82
91=cut 83=cut
92 84
93sub sleep { 85sub sleep {
94 my $current = $Coro::current; 86 my $current = $Coro::current;
95 my $timer = _new_timer(time + $_[0], sub { $current->ready }); 87 my $timer = AnyEvent->timer (after => $_[0], cb => sub { $current->ready });
96 Coro::schedule; 88 Coro::schedule;
97 $timer->cancel;
98} 89}
99 90
100=item $timer = new Coro::Timer at/after => xxx, cb => \&yyy; 91$Coro::idle = sub {
101 92 AnyEvent->one_event;
102Create a new timer. 93};
103
104=cut
105
106sub new {
107 my $class = shift;
108 my %arg = @_;
109
110 $arg{at} = time + delete $arg{after} if exists $arg{after};
111
112 _new_timer($arg{at}, $arg{cb});
113}
114
115my $timer;
116my @timer;
117
118unless ($override) {
119 $override = 1;
120 *_new_timer = sub {
121 my $self = bless [$_[0], $_[1]], Coro::Timer::simple;
122
123 # my version of rapid prototyping. guys, use a real event module!
124 @timer = sort { $a->[0] cmp $b->[0] } @timer, $self;
125
126 unless ($timer) {
127 $timer = new Coro sub {
128 my $NOW = time;
129 while (@timer) {
130 Coro::cede;
131 if ($NOW >= $timer[0][0]) {
132 my $next = shift @timer;
133 $next->[1] and $next->[1]->();
134 } else {
135 select undef, undef, undef, $timer[0][0] - $NOW;
136 $NOW = time;
137 }
138 };
139 undef $timer;
140 };
141 $timer->prio(Coro::PRIO_MIN);
142 $timer->ready;
143 }
144
145 $self;
146 };
147
148 *Coro::Timer::simple::cancel = sub {
149 @{$_[0]} = ();
150 };
151}
152
153=item $timer->cancel
154
155Cancel the timer (the callback will no longer be called). This method MUST
156be called to remove the timer from memory, otherwise it will never be
157freed!
158
159=cut
160 94
1611; 951;
162 96
163=back 97=back
164 98

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines