ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Event.pm
Revision: 1.23
Committed: Thu Aug 16 21:55:34 2001 UTC (22 years, 9 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +0 -0 lines
State: FILE REMOVED
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::Event - do events the coro-way
4
5 =head1 SYNOPSIS
6
7 use Coro;
8 use Coro::Event;
9
10 sub keyboard : Coro {
11 my $w = Coro::Event->io(fd => *STDIN, poll => 'r');
12 while() {
13 print "cmd> ";
14 my $ev = $w->next; my $cmd = <STDIN>;
15 unloop unless $cmd ne "";
16 print "data> ";
17 my $ev = $w->next; my $data = <STDIN>;
18 }
19 }
20
21 &loop;
22
23 =head1 DESCRIPTION
24
25 This module enables you to create programs using the powerful Event model
26 (and module), while retaining the linear style known from simple or
27 threaded programs.
28
29 This module provides a method and a function for every watcher type
30 (I<flavour>) (see L<Event>). The only difference between these and the
31 watcher constructors from Event is that you do not specify a callback
32 function - it will be managed by this module.
33
34 Your application should just create all necessary coroutines and then call
35 Coro::Event->main.
36
37 =over 4
38
39 =cut
40
41 package Coro::Event;
42
43 no warnings;
44
45 use Carp;
46
47 use Coro;
48 use Event qw(unloop); # we are re-exporting this, cooool!
49
50 use base 'Exporter';
51
52 @EXPORT = qw(loop unloop sweep);
53
54 $VERSION = 0.45;
55
56 =item $w = Coro::Event->flavour(args...)
57
58 Create and return a watcher of the given type.
59
60 Examples:
61
62 my $reader = Coro::Event->io(fd => $filehandle, poll => 'r');
63 $reader->next;
64
65 =cut
66
67 =item $w->next
68
69 Return the next event of the event queue of the watcher.
70
71 =cut
72
73 =item do_flavour(args...)
74
75 Create a watcher of the given type and immediately call it's next
76 method. This is less efficient then calling the constructor once and the
77 next method often, but it does save typing sometimes.
78
79 =cut
80
81 Event->add_hooks(prepare => sub {
82 &Coro::cede while &Coro::nready;
83 1e6;
84 });
85
86 sub std_cb {
87 my $w = $_[0]->w;
88 my $q = $w->private;
89 $q->[1] = $_[0];
90 if ($q->[0]) { # somebody waiting?
91 $q->[0]->ready;
92 } else {
93 $w->stop;
94 }
95 }
96
97 for my $flavour (qw(idle var timer io signal)) {
98 push @EXPORT, "do_$flavour";
99 my $new = \&{"Event::$flavour"};
100 my $class = "Coro::Event::$flavour";
101 @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour");
102 my $coronew = sub {
103 # how does one do method-call-by-name?
104 # my $w = $class->SUPER::$flavour(@_);
105
106 $_[0] eq Coro::Event::
107 or croak "event constructor \"Coro::Event->$flavour\" must be called as a static method";
108
109 my $q = []; # [$coro, $event]
110 my $w = $new->(
111 desc => $flavour,
112 @_,
113 cb => \&std_cb,
114 );
115 $w->private($q); # using private as attribute is pretty useless...
116 bless $w, $class; # reblessing due to broken Event
117 };
118 *{ $flavour } = $coronew;
119 *{"do_$flavour"} = sub {
120 unshift @_, Coro::Event::;
121 my $e = (&$coronew)->next;
122 $e->w->cancel;
123 $e;
124 };
125 }
126
127 sub next {
128 my $w = $_[0];
129 my $q = $w->private;
130 if ($q->[1]) { # event waiting?
131 $w->again unless $w->is_cancelled;
132 } elsif ($q->[0]) {
133 croak "only one coroutine can wait for an event";
134 } else {
135 local $q->[0] = $Coro::current;
136 &Coro::schedule;
137 }
138 pop @$q;
139 }
140
141 =item sweep
142
143 Similar to Event::one_event and Event::sweep: The idle task is called once
144 (this has the effect of jumping back into the Event loop once to serve new
145 events).
146
147 The reason this function exists is that you sometimes want to serve events
148 while doing other work. Calling C<Coro::cede> does not work because
149 C<cede> implies that the current coroutine is runnable and does not call
150 into the Event dispatcher.
151
152 =cut
153
154 sub sweep {
155 one_event(0); # for now
156 }
157
158 =item $result = loop([$timeout])
159
160 This is the version of C<loop> you should use instead of C<Event::loop>
161 when using this module - it will ensure correct scheduling in the presence
162 of events.
163
164 =begin comment
165
166 Unlike loop's counterpart it is not an error when no watchers are active -
167 loop silently returns in this case, as if unloop(undef) were called.
168
169 =end comment
170
171 =cut
172
173 sub loop(;$) {
174 local $Coro::idle = $Coro::current;
175 Coro::schedule; # become idle task, which is implicitly ready
176 &Event::loop;
177 }
178
179 =item unloop([$result])
180
181 Same as Event::unloop (provided here for your convinience only).
182
183 =cut
184
185 $Coro::idle = new Coro sub {
186 while () {
187 Event::one_event; # inefficient
188 Coro::schedule;
189 }
190 };
191
192 1;
193
194 =head1 AUTHOR
195
196 Marc Lehmann <pcg@goof.com>
197 http://www.goof.com/pcg/marc/
198
199 =cut
200