#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#  (C) Paul Evans, 2009-2012 -- leonerd@leonerd.org.uk

package CPS::Governor;

use strict;
use warnings;

use Carp;

our $VERSION = '0.19';

=head1 NAME

C<CPS::Governor> - control the iteration of the C<CPS> functions


Objects based on this abstract class are used by the C<gk*> variants of the
L<CPS> functions, to control their behavior. These objects are expected to
provide a method, C<again>, which the functions will use to re-invoke
iterations of loops, and so on. By providing a different implementation of
this method, governor objects can provide such behaviours as rate-limiting,
asynchronisation or parallelism, and integration with event-based IO




=head2 $gov = CPS::Governor->new

Must be called on a subclass which implements the C<again> method. Returns a
new instance of a governor object in that class.


sub new
   my $class = shift;
   $class->can( "again" ) or croak "Expected to be class that can ->again";
   return bless {}, $class;

# We're using this internally in gkpar() but not documenting it currently.
# Details are still experimental.
sub enter
   my $self = shift;
   $self->again( @_ );


Because this is an abstract class, instances of it can only be constructed on
a subclass which implements the following methods:


=head2 $gov->again( $code, @args )

Execute the function given in the C<CODE> reference C<$code>, passing in the
arguments C<@args>. If this is going to be executed immediately, it should
be invoked using a tail-call directly by the C<again> method, so that the
stack does not grow arbitrarily. This can be achieved by, for example:

 @_ = @args;
 goto &$code;

Alternatively, the L<Sub::Call::Tail> may be used to apply syntactic sugar,
allowing you to write instead:

 use Sub::Call::Tail;
 tail $code->( @args );



=head2 A Governor With A Time Delay

Consider the following subclass, which implements a C<CPS::Governor> subclass
that calls C<sleep()> between every invocation.

 package Governor::Sleep

 use base qw( CPS::Governor );

 sub new
    my $class = shift;
    my ( $delay ) = @_;

    my $self = $class->SUPER::new;
    $self->{delay} = $delay;

    return $self;

 sub again
    my $self = shift;
    my $code = shift;

    sleep $self->{delay};

    # @args are still in @_
    goto &$code;


=head1 SEE ALSO

=over 4

=item *

L<Sub::Call::Tail> - Tail calls for subroutines and methods


=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>