#  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

=head1 DESCRIPTION

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
frameworks.

=cut

=head1 CONSTRUCTOR

=cut

=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.

=cut

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( @_ );
}

=head1 SUBCLASS METHODS

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

=cut

=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 );

=cut

=head1 EXAMPLES

=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;
 }

=cut

=head1 SEE ALSO

=over 4

=item *

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

=back

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;