ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Timer.pm
Revision: 1.7
Committed: Sat Feb 9 18:53:03 2002 UTC (22 years, 5 months ago) by root
Branch: MAIN
Changes since 1.6: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::Timer - simple timer package, independent of used event loops
4
5 =head1 SYNOPSIS
6
7 use Coro::Timer;
8
9 =head1 DESCRIPTION
10
11 This package implements a simple timer callback system which works
12 independent of the event loop mechanism used. If no event mechanism is
13 used, it is emulated. The C<Coro::Event> module overwrites functions with
14 versions better suited.
15
16 This module is not subclassable.
17
18 =over 4
19
20 =cut
21
22 package Coro::Timer;
23
24 no warnings qw(uninitialized);
25
26 use Carp ();
27 use Exporter;
28
29 use Coro ();
30
31 BEGIN {
32 eval "use Time::HiRes 'time'";
33 }
34
35 $VERSION = 0.532;
36 @EXPORT_OK = qw(timeout sleep);
37
38 =item $flag = timeout $seconds;
39
40 This function will wake up the current coroutine after $seconds
41 seconds and sets $flag to true (it is false intiially). If $flag goes
42 out of scope earlier nothing happens. This is used to implement the
43 C<timed_down>, C<timed_wait> etc. primitives. It is used like this:
44
45 sub timed_wait {
46 my $timeout = Coro::Timer::timeout 60;
47
48 while (condition false) {
49 schedule; # wait until woken up or timeout
50 return 0 if $timeout; # timed out
51 }
52 return 1; # condition satisfied
53 }
54
55 =cut
56
57 # deep magic, expecially the double indirection :(:(
58 sub timeout($) {
59 my $self = \\my $timer;
60 my $current = $Coro::current;
61 $timer = _new_timer(time + $_[0], sub {
62 undef $timer; # set flag
63 $current->ready;
64 });
65 bless $self, Coro::timeout::;
66 }
67
68 package Coro::timeout;
69
70 sub bool { !${${$_[0]}} }
71 sub DESTROY { ${${$_[0]}}->cancel }
72
73 use overload 'bool' => \&bool, '0+' => \&bool;
74
75 package Coro::Timer;
76
77 =item sleep $seconds
78
79 This function works like the built-in sleep, except maybe more precise
80 and, most important, without blocking other coroutines.
81
82 =cut
83
84 sub sleep {
85 my $current = $Coro::current;
86 _new_timer(time + $_[0], sub { $current->ready });
87 Coro::schedule;
88 }
89
90 =item $timer = new Coro::Timer at/after => xxx, cb => \&yyy;
91
92 Create a new timer.
93
94 =cut
95
96 sub new {
97 my $class = shift;
98 my %arg = @_;
99
100 $arg{at} = time + delete $arg{after} if exists $arg{after};
101
102 _new_timer($arg{at}, $arg{cb});
103 }
104
105 my $timer;
106 my @timer;
107
108 unless ($override) {
109 $override = 1;
110 *_new_timer = sub {
111 my $self = bless [$_[0], $_[1]], Coro::Timer::simple;
112
113 # my version of rapid prototyping. guys, use a real event module!
114 @timer = sort { $a->[0] cmp $b->[0] } @timer, $self;
115
116 unless ($timer) {
117 $timer = new Coro sub {
118 my $NOW = time;
119 while (@timer) {
120 Coro::cede;
121 if ($NOW >= $timer[0][0]) {
122 my $next = shift @timer;
123 $next->[1] and $next->[1]->();
124 } else {
125 select undef, undef, undef, $timer[0][0] - $NOW;
126 $NOW = time;
127 }
128 };
129 undef $timer;
130 };
131 $timer->prio(Coro::PRIO_MIN);
132 $timer->ready;
133 }
134
135 $self;
136 };
137
138 *Coro::Timer::simple::cancel = sub {
139 @{$_[0]} = ();
140 };
141 }
142
143 =item $timer->cancel
144
145 Cancel the timer (the callback will no longer be called).
146
147 =cut
148
149 1;
150
151 =back
152
153 =head1 AUTHOR
154
155 Marc Lehmann <pcg@goof.com>
156 http://www.goof.com/pcg/marc/
157
158 =cut
159