ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Event/Event.pm
Revision: 1.54
Committed: Fri Apr 25 04:28:50 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.53: +1 -1 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 # wait for input on stdin for one second
24
25 Coro::Event::do_io (fd => \*STDIN, timeout => 1) & Event::Watcher::R
26 or die "no input received";
27
28 # use a separate coroutine for event processing, if impossible in main:
29 Coro::async { Event::loop };
30
31 =head1 DESCRIPTION
32
33 This module enables you to create programs using the powerful Event model
34 (and module), while retaining the linear style known from simple or
35 threaded programs.
36
37 This module provides a method and a function for every watcher type
38 (I<flavour>) (see L<Event>). The only difference between these and the
39 watcher constructors from Event is that you do not specify a callback
40 function - it will be managed by this module.
41
42 Your application should just create all necessary coroutines and then call
43 Coro::Event::loop.
44
45 Please note that even programs or modules (such as
46 L<Coro::Handle|Coro::Handle>) that use "traditional"
47 event-based/continuation style will run more efficient with this module
48 then when using only Event.
49
50 =head1 WARNING
51
52 Please note that Event does not support coroutines or threads. That
53 means that you B<MUST NOT> block in an event callback. Again: In Event
54 callbacks, you I<must never ever> call a Coroutine function that blocks
55 the current coroutine.
56
57 While this seems to work superficially, it will eventually cause memory
58 corruption and often results in deadlocks.
59
60 Best practise is to always use B<Coro::unblock_sub> for your callbacks.
61
62 =head1 SEMANTICS
63
64 Whenever Event blocks (e.g. in a call to C<one_event>, C<loop> etc.),
65 this module cede's to all other coroutines with the same or higher
66 priority. When any coroutines of lower priority are ready, it will not
67 block but run one of them and then check for events.
68
69 The effect is that coroutines with the same or higher priority than
70 the blocking coroutine will keep Event from checking for events, while
71 coroutines with lower priority are being run, but Event checks for new
72 events after every cede.
73
74 =head1 FUNCTIONS
75
76 =over 4
77
78 =cut
79
80 package Coro::Event;
81
82 no warnings;
83
84 use Carp;
85 no warnings;
86
87 use Coro;
88 use Coro::Timer;
89 use Event qw(loop unloop); # we are re-exporting this, cooool!
90
91 use XSLoader;
92
93 use base Exporter::;
94
95 our @EXPORT = qw(loop unloop sweep);
96
97 BEGIN {
98 our $VERSION = 4.6;
99
100 local $^W = 0; # avoid redefine warning for Coro::ready;
101 XSLoader::load __PACKAGE__, $VERSION;
102 }
103
104 =item $w = Coro::Event->flavour (args...)
105
106 Create and return a watcher of the given type.
107
108 Examples:
109
110 my $reader = Coro::Event->io(fd => $filehandle, poll => 'r');
111 $reader->next;
112
113 =cut
114
115 =item $w->next
116
117 Wait for and return the next event of the event queue of the watcher. The
118 returned event objects support two methods only: C<hits> and C<got>, both
119 of which return integers: the number this watcher was hit for this event,
120 and the mask of poll events received.
121
122 =cut
123
124 =item do_flavour args...
125
126 Create a watcher of the given type and immediately call it's next method,
127 returning the event.
128
129 This is less efficient then calling the constructor once and the next
130 method often, but it does save typing sometimes.
131
132 =cut
133
134 for my $flavour (qw(idle var timer io signal)) {
135 push @EXPORT, "do_$flavour";
136 my $new = \&{"Event::$flavour"};
137 my $class = "Coro::Event::$flavour";
138 my $type = $flavour eq "io" ? 1 : 0;
139 @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour");
140 my $coronew = sub {
141 # how does one do method-call-by-name?
142 # my $w = $class->SUPER::$flavour(@_);
143
144 shift eq Coro::Event::
145 or croak "event constructor \"Coro::Event->$flavour\" must be called as a static method";
146
147 my $w = $new->($class,
148 desc => $flavour,
149 @_,
150 parked => 1,
151 );
152
153 _install_std_cb $w, $type;
154
155 # reblessing due to Event being broken
156 bless $w, $class
157 };
158 *{ $flavour } = $coronew;
159 *{"do_$flavour"} = sub {
160 unshift @_, Coro::Event::;
161 @_ = &$coronew;
162 &Coro::schedule while &_next;
163 $_[0]->cancel;
164 &_event
165 };
166 }
167
168 # do schedule in perl to avoid forcing a stack allocation.
169 # this is about 10% slower, though.
170 sub next($) {
171 &Coro::schedule while &_next;
172 &_event
173 }
174
175 sub Coro::Event::Event::hits { $_[0][3] }
176 sub Coro::Event::Event::got { $_[0][4] }
177
178 =item sweep
179
180 Similar to Event::one_event and Event::sweep: The idle task is called once
181 (this has the effect of jumping back into the Event loop once to serve new
182 events).
183
184 The reason this function exists is that you sometimes want to serve events
185 while doing other work. Calling C<Coro::cede> does not work because
186 C<cede> implies that the current coroutine is runnable and does not call
187 into the Event dispatcher.
188
189 =cut
190
191 sub sweep {
192 Event::one_event 0; # for now
193 }
194
195 =item $result = loop([$timeout])
196
197 This is the version of C<loop> you should use instead of C<Event::loop>
198 when using this module - it will ensure correct scheduling in the presence
199 of events.
200
201 =item unloop([$result])
202
203 Same as Event::unloop (provided here for your convinience only).
204
205 =cut
206
207 # very inefficient
208 our $event_idle = new Coro sub {
209 while () {
210 &Event::one_event;
211 &Coro::schedule;
212 }
213 };
214 $event_idle->{desc} = "[Event idle process]";
215
216 $Coro::idle = sub { $event_idle->ready };
217
218 1;
219
220 =back
221
222 =head1 AUTHOR
223
224 Marc Lehmann <schmorp@schmorp.de>
225 http://home.schmorp.de/
226
227 =cut
228