ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
(Generate patch)

Comparing Coro/Coro.pm (file contents):
Revision 1.37 by root, Mon Sep 24 02:25:44 2001 UTC vs.
Revision 1.40 by root, Sun Oct 28 17:00:05 2001 UTC

38 38
39use Coro::State; 39use Coro::State;
40 40
41use base Exporter; 41use base Exporter;
42 42
43$VERSION = 0.5; 43$VERSION = 0.51;
44 44
45@EXPORT = qw(async cede schedule terminate current); 45@EXPORT = qw(async cede schedule terminate current);
46%EXPORT_TAGS = ( 46%EXPORT_TAGS = (
47 prio => [qw(PRIO_MAX PRIO_HIGH PRIO_NORMAL PRIO_LOW PRIO_IDLE PRIO_MIN)], 47 prio => [qw(PRIO_MAX PRIO_HIGH PRIO_NORMAL PRIO_LOW PRIO_IDLE PRIO_MIN)],
48); 48);
116}; 116};
117 117
118# this coroutine is necessary because a coroutine 118# this coroutine is necessary because a coroutine
119# cannot destroy itself. 119# cannot destroy itself.
120my @destroy; 120my @destroy;
121my $manager;
121my $manager = new Coro sub { 122$manager = new Coro sub {
122 while() { 123 while() {
123 # by overwriting the state object with the manager we destroy it 124 # by overwriting the state object with the manager we destroy it
124 # while still being able to schedule this coroutine (in case it has 125 # while still being able to schedule this coroutine (in case it has
125 # been readied multiple times. this is harmless since the manager 126 # been readied multiple times. this is harmless since the manager
126 # can be called as many times as neccessary and will always 127 # can be called as many times as neccessary and will always
127 # remove itself from the runqueue 128 # remove itself from the runqueue
129 while (@destroy) {
130 my $coro = pop @destroy;
131 $coro->{status} ||= [];
132 $_->ready for @{delete $coro->{join} || []};
128 (pop @destroy)->{_coro_state} = $manager->{_coro_state} while @destroy; 133 $coro->{_coro_state} = $manager->{_coro_state};
134 }
129 &schedule; 135 &schedule;
130 } 136 }
131}; 137};
132 138
133# static methods. not really. 139# static methods. not really.
175ready queue and calls C<schedule>, which has the effect of giving up the 181ready queue and calls C<schedule>, which has the effect of giving up the
176current "timeslice" to other coroutines of the same or higher priority. 182current "timeslice" to other coroutines of the same or higher priority.
177 183
178=cut 184=cut
179 185
180=item terminate 186=item terminate [arg...]
181 187
182Terminates the current process. 188Terminates the current process.
183 189
184Future versions of this function will allow result arguments. 190Future versions of this function will allow result arguments.
185 191
186=cut 192=cut
187 193
188sub terminate { 194sub terminate {
195 $current->{status} = [@_];
189 $current->cancel; 196 $current->cancel;
190 &schedule; 197 &schedule;
191 die; # NORETURN 198 die; # NORETURN
192} 199}
193 200
202=over 4 209=over 4
203 210
204=item new Coro \&sub [, @args...] 211=item new Coro \&sub [, @args...]
205 212
206Create a new process and return it. When the sub returns the process 213Create a new process and return it. When the sub returns the process
207automatically terminates. To start the process you must first put it into 214automatically terminates as if C<terminate> with the returned values were
208the ready queue by calling the ready method. 215called. To start the process you must first put it into the ready queue by
216calling the ready method.
209 217
210The coderef you submit MUST NOT be a closure that refers to variables 218The coderef you submit MUST NOT be a closure that refers to variables
211in an outer scope. This does NOT work. Pass arguments into it instead. 219in an outer scope. This does NOT work. Pass arguments into it instead.
212 220
213=cut 221=cut
223 }, $class; 231 }, $class;
224} 232}
225 233
226=item $process->ready 234=item $process->ready
227 235
228Put the current process into the ready queue. 236Put the given process into the ready queue.
229 237
230=cut 238=cut
231 239
232=item $process->cancel 240=item $process->cancel
233 241
237 245
238sub cancel { 246sub cancel {
239 push @destroy, $_[0]; 247 push @destroy, $_[0];
240 $manager->ready; 248 $manager->ready;
241 &schedule if $current == $_[0]; 249 &schedule if $current == $_[0];
250}
251
252=item $process->join
253
254Wait until the coroutine terminates and return any values given to the
255C<terminate> function. C<join> can be called multiple times from multiple
256processes.
257
258=cut
259
260sub join {
261 my $self = shift;
262 unless ($self->{status}) {
263 push @{$self->{join}}, $current;
264 &schedule;
265 }
266 wantarray ? @{$self->{status}} : $self->{status}[0];
242} 267}
243 268
244=item $oldprio = $process->prio($newprio) 269=item $oldprio = $process->prio($newprio)
245 270
246Sets the priority of the process. Higher priority processes get run before 271Sets the priority of the process. Higher priority processes get run before

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines