ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Event/Event.pm
Revision: 1.1
Committed: Thu Aug 16 21:55:34 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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     &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     @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour");
103     my $coronew = sub {
104     # how does one do method-call-by-name?
105     # my $w = $class->SUPER::$flavour(@_);
106    
107     $_[0] eq Coro::Event::
108     or croak "event constructor \"Coro::Event->$flavour\" must be called as a static method";
109    
110     my $q = []; # [$coro, $event]
111     my $w = $new->(
112     desc => $flavour,
113     @_,
114     cb => \&std_cb,
115     );
116     $w->private($q); # using private as attribute is pretty useless...
117     bless $w, $class; # reblessing due to broken Event
118     };
119     *{ $flavour } = $coronew;
120     *{"do_$flavour"} = sub {
121     unshift @_, Coro::Event::;
122     my $e = (&$coronew)->next;
123     $e->w->cancel;
124     $e;
125     };
126     }
127    
128     sub next {
129     my $w = $_[0];
130     my $q = $w->private;
131     if ($q->[1]) { # event waiting?
132     $w->again unless $w->is_cancelled;
133     } elsif ($q->[0]) {
134     croak "only one coroutine can wait for an event";
135     } else {
136     local $q->[0] = $Coro::current;
137     &Coro::schedule;
138     }
139     pop @$q;
140     }
141    
142     =item sweep
143    
144     Similar to Event::one_event and Event::sweep: The idle task is called once
145     (this has the effect of jumping back into the Event loop once to serve new
146     events).
147    
148     The reason this function exists is that you sometimes want to serve events
149     while doing other work. Calling C<Coro::cede> does not work because
150     C<cede> implies that the current coroutine is runnable and does not call
151     into the Event dispatcher.
152    
153     =cut
154    
155     sub sweep {
156     one_event(0); # for now
157     }
158    
159     =item $result = loop([$timeout])
160    
161     This is the version of C<loop> you should use instead of C<Event::loop>
162     when using this module - it will ensure correct scheduling in the presence
163     of events.
164    
165     =begin comment
166    
167     Unlike loop's counterpart it is not an error when no watchers are active -
168     loop silently returns in this case, as if unloop(undef) were called.
169    
170     =end comment
171    
172     =cut
173    
174     sub loop(;$) {
175     local $Coro::idle = $Coro::current;
176     Coro::schedule; # become idle task, which is implicitly ready
177     &Event::loop;
178     }
179    
180     =item unloop([$result])
181    
182     Same as Event::unloop (provided here for your convinience only).
183    
184     =cut
185    
186     $Coro::idle = new Coro sub {
187     while () {
188     Event::one_event; # inefficient
189     Coro::schedule;
190     }
191     };
192    
193     1;
194    
195     =head1 AUTHOR
196    
197     Marc Lehmann <pcg@goof.com>
198     http://www.goof.com/pcg/marc/
199    
200     =cut
201