ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Event.pm
Revision: 1.9
Committed: Sat Jul 21 18:21:45 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.8: +7 -4 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 modell
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 Event qw(unloop); # we are re-exporting this, cooool!
48
49 use base 'Event';
50 use base 'Exporter';
51
52 @EXPORT = qw(loop unloop sweep);
53
54 $VERSION = 0.10;
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 for my $flavour (qw(idle var timer io signal)) {
82 push @EXPORT, "do_$flavour";
83 my $new = \&{"Event::$flavour"};
84 my $class = "Coro::Event::$flavour";
85 @{"${class}::ISA"} = ("Coro::Event", "Event::$flavour");
86 my $coronew = sub {
87 # how does one do method-call-by-name?
88 # my $w = $class->SUPER::$flavour(@_);
89
90 $_[0] eq Coro::Event::
91 or croak "event constructor \"Coro::Event->$flavour\" must be called as a static method";
92
93 my $w;
94 my $q = []; # [$coro, $event]
95 $w = $new->(@_, cb => sub {
96 $q->[1] = $_[0];
97 if ($q->[0]) { # somebody waiting?
98 $q->[0]->ready;
99 Coro::schedule;
100 } else {
101 $w->stop;
102 }
103 });
104 $w->private($q); # using private as attribute is pretty useless...
105 bless $w, $class; # reblessing due to broken Event
106 };
107 *{ $flavour } = $coronew;
108 *{"do_$flavour"} = sub {
109 unshift @_, $class;
110 (&$coronew)->next;
111 };
112 }
113
114 sub next {
115 my $q = $_[0]->private;
116 croak "only one coroutine can wait for an event" if $q->[0];
117 if (!$q->[1]) { # no event waiting?
118 local $q->[0] = $Coro::current;
119 Coro::schedule;
120 } else {
121 $_[0]->again unless $_[0]->is_canceled;
122 }
123 delete $q->[1];
124 }
125
126 =item sweep
127
128 Similar to Event::one_event and Event::sweep: The idle task is called once
129 (this has the effect of jumping back into the Event loop once to serve new
130 events).
131
132 =cut
133
134 sub sweep {
135 $Coro::idle->ready;
136 Coro::yield;
137 }
138
139 =item $result = loop([$timeout])
140
141 This is the version of C<loop> you should use instead of C<Event::loop>
142 when using this module - it will ensure correct scheduling in the presence
143 of events.
144
145 =cut
146
147 sub loop(;$) {
148 local $Coro::idle = $Coro::current;
149 Coro::schedule; # become idle task, which is implicitly ready
150 &Event::loop;
151 }
152
153 =item unloop([$result])
154
155 Same as Event::unloop (provided here for your convinience only).
156
157 =cut
158
159 $Coro::idle = new Coro sub {
160 Event::one_event; # inefficient
161 };
162
163 1;
164
165 =head1 BUGS
166
167 This module is implemented straightforward using Coro::Channel and thus
168 not as efficient as possible.
169
170 =head1 AUTHOR
171
172 Marc Lehmann <pcg@goof.com>
173 http://www.goof.com/pcg/marc/
174
175 =cut
176