ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Event.pm
Revision: 1.7
Committed: Sat Jul 21 02:49:09 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.6: +18 -1 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 root 1.3 unloop unless $cmd ne "";
16 root 1.1 print "data> ";
17     my $ev = $w->next; my $data = <STDIN>;
18     }
19     }
20    
21 root 1.3 &loop;
22    
23 root 1.1 =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 root 1.3 use Carp;
46    
47     use Event qw(unloop); # we are re-exporting this, cooool!
48 root 1.1
49     use base 'Event';
50     use base 'Exporter';
51    
52 root 1.3 @EXPORT = qw(loop unloop);
53    
54 root 1.7 $VERSION = 0.09;
55 root 1.1
56 root 1.3 =item $w = Coro::Event->flavour(args...)
57 root 1.1
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 root 1.3 =item $w->next
68    
69     Return the next event of the event queue of the watcher.
70    
71     =cut
72    
73 root 1.1 =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 root 1.2 my $w;
91 root 1.3 my $q = []; # [$coro, $event]
92     $w = $new->(@_, cb => sub {
93     $q->[1] = $_[0];
94     if ($q->[0]) { # somebody waiting?
95     $q->[0]->ready;
96 root 1.5 Coro::schedule;
97 root 1.3 } else {
98     $w->stop;
99     }
100     });
101 root 1.1 $w->private($q); # using private as attribute is pretty useless...
102     bless $w, $class; # reblessing due to broken Event
103     };
104     *{ $flavour } = $coronew;
105     *{"do_$flavour"} = sub {
106     unshift @_, $class;
107     (&$coronew)->next;
108     };
109     }
110    
111 root 1.3 sub next {
112     my $q = $_[0]->private;
113     croak "only one coroutine can wait for an event" if $q->[0];
114     if (!$q->[1]) { # no event waiting?
115     local $q->[0] = $Coro::current;
116     Coro::schedule;
117     } else {
118     $_[0]->again;
119     }
120     delete $q->[1];
121     }
122    
123 root 1.7 =item idle
124    
125     Similar to Event::one_event and Event::sweep: The idle task is called once
126     (this has the effect of jumping back into the Event loop once to serve new
127     events).
128    
129     =cut
130    
131     sub idle {
132     $Coro::idle->ready;
133     Coro::yield;
134     }
135    
136 root 1.3 =item $result = loop([$timeout])
137 root 1.1
138 root 1.3 This is the version of C<loop> you should use instead of C<Event::loop>
139     when using this module - it will ensure correct scheduling in the presence
140     of events.
141 root 1.1
142     =cut
143    
144 root 1.3 sub loop(;$) {
145     local $Coro::idle = $Coro::current;
146     Coro::schedule; # become idle task, which is implicitly ready
147     &Event::loop;
148 root 1.1 }
149    
150 root 1.3 =item unloop([$result])
151    
152     Same as Event::unloop (provided here for your convinience only).
153 root 1.1
154     =cut
155 root 1.7
156     $Coro::idle = new Coro sub {
157     Event::one_event; # inefficient
158     };
159 root 1.1
160     1;
161    
162     =head1 BUGS
163    
164     This module is implemented straightforward using Coro::Channel and thus
165     not as efficient as possible.
166    
167     =head1 AUTHOR
168    
169     Marc Lehmann <pcg@goof.com>
170     http://www.goof.com/pcg/marc/
171    
172     =cut
173