ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Event/Event.pm
Revision: 1.2
Committed: Fri Aug 17 01:45:39 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.1: +45 -31 lines
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 BEGIN {
55 $VERSION = 0.45;
56
57 require XSLoader;
58 XSLoader::load Coro::Event, $VERSION;
59 }
60
61 =item $w = Coro::Event->flavour(args...)
62
63 Create and return a watcher of the given type.
64
65 Examples:
66
67 my $reader = Coro::Event->io(fd => $filehandle, poll => 'r');
68 $reader->next;
69
70 =cut
71
72 =item $w->next
73
74 Return the next event of the event queue of the watcher.
75
76 =cut
77
78 =item do_flavour(args...)
79
80 Create a watcher of the given type and immediately call it's next
81 method. This is less efficient then calling the constructor once and the
82 next method often, but it does save typing sometimes.
83
84 =cut
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 # &Coro::schedule;
93 # } else {
94 # $w->stop;
95 # }
96 #}
97
98 for my $flavour (qw(idle var timer io signal)) {
99 push @EXPORT, "do_$flavour";
100 my $new = \&{"Event::$flavour"};
101 my $class = "Coro::Event::$flavour";
102 my $type = $flavour eq "io" ? 1 : 0;
103 @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour");
104 my $coronew = sub {
105 # how does one do method-call-by-name?
106 # my $w = $class->SUPER::$flavour(@_);
107
108 $_[0] eq Coro::Event::
109 or croak "event constructor \"Coro::Event->$flavour\" must be called as a static method";
110
111 my $q = []; # [$coro, $event]
112 my $w = $new->(
113 desc => $flavour,
114 @_,
115 parked => 1,
116 );
117 _install_std_cb($w, $type);
118 bless $w, $class; # reblessing due to broken Event
119 };
120 *{ $flavour } = $coronew;
121 *{"do_$flavour"} = sub {
122 unshift @_, Coro::Event::;
123 my $e = (&$coronew)->next;
124 $e->w->cancel;
125 $e;
126 };
127 }
128
129 # double calls to avoid stack-cloning ;()
130 # is about 20% slower, though.
131 sub next($) {
132 &_next0;
133 &Coro::schedule;
134 &_next1;
135 }
136
137 #sub next {
138 # my $w = $_[0];
139 # my $q = $w->private;
140 # if ($q->[1]) { # event waiting?
141 # $w->again unless $w->is_cancelled;
142 # } elsif ($q->[0]) {
143 # croak "only one coroutine can wait for an event";
144 # } else {
145 # local $q->[0] = $Coro::current;
146 # &Coro::schedule;
147 # }
148 # pop @$q;
149 #}
150
151 sub Coro::Event::Ev::w { $_[0][2] }
152 sub Coro::Event::Ev::got { $_[0][3] }
153 sub Coro::Event::Ev::prio { croak "prio not supported yet, please mail to pcg\@goof.com" }
154 sub Coro::Event::Ev::hits { croak "prio not supported yet, please mail to pcg\@goof.com" }
155
156 =item sweep
157
158 Similar to Event::one_event and Event::sweep: The idle task is called once
159 (this has the effect of jumping back into the Event loop once to serve new
160 events).
161
162 The reason this function exists is that you sometimes want to serve events
163 while doing other work. Calling C<Coro::cede> does not work because
164 C<cede> implies that the current coroutine is runnable and does not call
165 into the Event dispatcher.
166
167 =cut
168
169 sub sweep {
170 one_event(0); # for now
171 }
172
173 =item $result = loop([$timeout])
174
175 This is the version of C<loop> you should use instead of C<Event::loop>
176 when using this module - it will ensure correct scheduling in the presence
177 of events.
178
179 =begin comment
180
181 Unlike loop's counterpart it is not an error when no watchers are active -
182 loop silently returns in this case, as if unloop(undef) were called.
183
184 =end comment
185
186 =cut
187
188 sub loop(;$) {
189 local $Coro::idle = $Coro::current;
190 Coro::schedule; # become idle task, which is implicitly ready
191 &Event::loop;
192 }
193
194 =item unloop([$result])
195
196 Same as Event::unloop (provided here for your convinience only).
197
198 =cut
199
200 $Coro::idle = new Coro sub {
201 while () {
202 Event::one_event; # inefficient
203 Coro::schedule;
204 }
205 };
206
207 1;
208
209 =head1 AUTHOR
210
211 Marc Lehmann <pcg@goof.com>
212 http://www.goof.com/pcg/marc/
213
214 =cut
215