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

# 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 root 1.2 BEGIN {
55     $VERSION = 0.45;
56    
57     require XSLoader;
58     XSLoader::load Coro::Event, $VERSION;
59     }
60 root 1.1
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 root 1.2 #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 root 1.1
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 root 1.2 my $type = $flavour eq "io" ? 1 : 0;
103 root 1.1 @{"${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 root 1.2 parked => 1,
116 root 1.1 );
117 root 1.2 _install_std_cb($w, $type);
118 root 1.1 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 root 1.2 # double calls to avoid stack-cloning ;()
130     # is about 20% slower, though.
131     sub next($) {
132     &_next0;
133     &Coro::schedule;
134     &_next1;
135 root 1.1 }
136 root 1.2
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 root 1.1
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