CPS

 view release on metacpan or  search on metacpan

lib/CPS/Governor/Deferred.pm  view on Meta::CPAN

#
#  (C) Paul Evans, 2009 -- leonerd@leonerd.org.uk

package CPS::Governor::Deferred;

use strict;
use warnings;

use base qw( CPS::Governor );

our $VERSION = '0.19';

=head1 NAME

C<CPS::Governor::Deferred> - iterate at some later point

=head1 SYNOPSIS

 use CPS qw( gkforeach );
 use CPS::Governor::Deferred;

 my $gov = CPS::Governor::Deferred->new;

 gkforeach( $gov, [ 1 .. 10 ],
    sub { 
       my ( $item, $knext ) = @_;

       print "A$item ";
       goto &$knext;
    },
    sub {},
 );

 gkforeach( $gov, [ 1 .. 10 ],
    sub {
       my ( $item, $knext ) = @_;

       print "B$item ";
       goto &$knext;
    },
    sub {},
 );

 $gov->flush;

=head1 DESCRIPTION

This L<CPS::Governor> allows the functions using it to delay their iteration
until some later point when the containing program invokes it. This allows two
main advantages:

=over 4

=item *

CPU-intensive operations may be split apart and mixed with other IO operations

=item *

Multiple control functions may be executed in pseudo-parallel, interleaving
iterations of each giving a kind of concurrency

=back

These are achieved by having the governor store a list of code references that
need to be invoked, rather than invoking them immediately. These references
can then be invoked later, perhaps by using an idle watcher in an event
framework.

Because each code reference hasn't yet been invoked by the time the C<again>
method is called, the original caller is free to store more pending references
with the governor. This allows multiple control functions to be interleaved,
as in the C<A> and C<B> example above.

=cut

=head1 CONSTRUCTOR

=cut

=head2 $gov = CPS::Governor::Deferred->new( %args )

Returns a new instance of a C<CPS::Governor::Deferred> object. Requires no
parameters but may take any of the following to adjust its default behaviour:

=over 8

=item defer_after => INT

If given some positive number, C<$n> then the first C<$n-1> invocations of the
C<again> method will in fact be executed immediately. Thereafter they will be
enqueued in the normal mechanism. This gives the effect that longrunning loops
will be executed in batches of C<$n>.

If not supplied then every invocation of C<again> will use the queueing
mechanism.

=back

=cut

sub new
{
   my $class = shift;
   my %args = @_;

   my $self = $class->SUPER::new( %args );

   $self->{defer_after} = $args{defer_after} || 0;

   return $self;
}

sub again
{
   my $self = shift;

   if( $self->{defer_after} and ++$self->{count} < $self->{defer_after} ) {
      my $code = shift;
      # args still in @_



( run in 0.512 second using v1.01-cache-2.11-cpan-71847e10f99 )