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

Comparing Coro/Coro.pm (file contents):
Revision 1.225 by root, Wed Nov 19 15:29:57 2008 UTC vs.
Revision 1.229 by root, Thu Nov 20 06:32:55 2008 UTC

149 for @{ delete $self->{_on_destroy} || [] }; 149 for @{ delete $self->{_on_destroy} || [] };
150} 150}
151 151
152# this coroutine is necessary because a coroutine 152# this coroutine is necessary because a coroutine
153# cannot destroy itself. 153# cannot destroy itself.
154my @destroy; 154our @destroy;
155my $manager; 155our $manager;
156 156
157$manager = new Coro sub { 157$manager = new Coro sub {
158 while () { 158 while () {
159 (shift @destroy)->_cancel 159 (shift @destroy)->_cancel
160 while @destroy; 160 while @destroy;
212Similar to C<async>, but uses a coroutine pool, so you should not call 212Similar to C<async>, but uses a coroutine pool, so you should not call
213terminate or join on it (although you are allowed to), and you get a 213terminate or join on it (although you are allowed to), and you get a
214coroutine that might have executed other code already (which can be good 214coroutine that might have executed other code already (which can be good
215or bad :). 215or bad :).
216 216
217On the plus side, this function is faster than creating (and destroying) 217On the plus side, this function is about twice as fast as creating (and
218a completly new coroutine, so if you need a lot of generic coroutines in 218destroying) a completely new coroutine, so if you need a lot of generic
219quick successsion, use C<async_pool>, not C<async>. 219coroutines in quick successsion, use C<async_pool>, not C<async>.
220 220
221The code block is executed in an C<eval> context and a warning will be 221The code block is executed in an C<eval> context and a warning will be
222issued in case of an exception instead of terminating the program, as 222issued in case of an exception instead of terminating the program, as
223C<async> does. As the coroutine is being reused, stuff like C<on_destroy> 223C<async> does. As the coroutine is being reused, stuff like C<on_destroy>
224will not work in the expected way, unless you call terminate or cancel, 224will not work in the expected way, unless you call terminate or cancel,
247our $POOL_SIZE = 8; 247our $POOL_SIZE = 8;
248our $POOL_RSS = 16 * 1024; 248our $POOL_RSS = 16 * 1024;
249our @async_pool; 249our @async_pool;
250 250
251sub pool_handler { 251sub pool_handler {
252 my $cb;
253
254 while () { 252 while () {
255 eval { 253 eval {
256 while () { 254 &{&_pool_handler} while 1;
257 _pool_1 $cb;
258 &$cb;
259 _pool_2 $cb;
260 &schedule;
261 }
262 }; 255 };
263 256
264 if ($@) {
265 last if $@ eq "\3async_pool terminate\2\n";
266 warn $@; 257 warn $@ if $@;
267 }
268 } 258 }
269}
270
271sub async_pool(&@) {
272 # this is also inlined into the unblock_scheduler
273 my $coro = (pop @async_pool) || new Coro \&pool_handler;
274
275 $coro->{_invoke} = [@_];
276 $coro->ready;
277
278 $coro
279} 259}
280 260
281=back 261=back
282 262
283=head2 STATIC METHODS 263=head2 STATIC METHODS
340program calls this function, there will be some one-time resource leak. 320program calls this function, there will be some one-time resource leak.
341 321
342=cut 322=cut
343 323
344sub terminate { 324sub terminate {
345 $current->cancel (@_); 325 $current->{_status} = [@_];
326 push @destroy, $current;
327 $manager->ready;
328 do { &schedule } while 1;
346} 329}
347 330
348sub killall { 331sub killall {
349 for (Coro::State::list) { 332 for (Coro::State::list) {
350 $_->cancel 333 $_->cancel
399 382
400=cut 383=cut
401 384
402sub cancel { 385sub cancel {
403 my $self = shift; 386 my $self = shift;
404 $self->{_status} = [@_];
405 387
406 if ($current == $self) { 388 if ($current == $self) {
407 push @destroy, $self; 389 terminate @_;
408 $manager->ready;
409 &schedule while 1;
410 } else { 390 } else {
391 $self->{_status} = [@_];
411 $self->_cancel; 392 $self->_cancel;
412 } 393 }
413} 394}
395
396=item $coroutine->schedule_to
397
398Puts the current coroutine to sleep (like C<Coro::schedule>), but instead
399of continuing with the next coro from the ready queue, always switch to
400the given coroutine object (regardless of priority etc.). The readyness
401state of that coroutine isn't changed.
402
403This is an advanced method for special cases - I'd love to hear about any
404uses for this one.
405
406=item $coroutine->cede_to
407
408Like C<schedule_to>, but puts the current coroutine into the ready
409queue. This has the effect of temporarily switching to the given
410coroutine, and continuing some time later.
411
412This is an advanced method for special cases - I'd love to hear about any
413uses for this one.
414 414
415=item $coroutine->throw ([$scalar]) 415=item $coroutine->throw ([$scalar])
416 416
417If C<$throw> is specified and defined, it will be thrown as an exception 417If C<$throw> is specified and defined, it will be thrown as an exception
418inside the coroutine at the next convenient point in time. Otherwise 418inside the coroutine at the next convenient point in time. Otherwise
609# return immediately and can be reused) and because we cannot cede 609# return immediately and can be reused) and because we cannot cede
610# inside an event callback. 610# inside an event callback.
611our $unblock_scheduler = new Coro sub { 611our $unblock_scheduler = new Coro sub {
612 while () { 612 while () {
613 while (my $cb = pop @unblock_queue) { 613 while (my $cb = pop @unblock_queue) {
614 # this is an inlined copy of async_pool 614 &async_pool (@$cb);
615 my $coro = (pop @async_pool) || new Coro \&pool_handler;
616 615
617 $coro->{_invoke} = $cb;
618 $coro->ready;
619 cede; # for short-lived callbacks, this reduces pressure on the coro pool 616 # for short-lived callbacks, this reduces pressure on the coro pool
617 # as the chance is very high that the async_poll coro will be back
618 # in the idle state when cede returns
619 cede;
620 } 620 }
621 schedule; # sleep well 621 schedule; # sleep well
622 } 622 }
623}; 623};
624$unblock_scheduler->{desc} = "[unblock_sub scheduler]"; 624$unblock_scheduler->{desc} = "[unblock_sub scheduler]";

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines