IO-Lambda
view release on metacpan or search on metacpan
lib/IO/Lambda.pm view on Meta::CPAN
sub is_waiting { not($_[0]->{stopped}) and @{$_[0]->{in}} }
sub is_passive { not($_[0]->{stopped}) and not(@{$_[0]->{in}}) }
sub is_active { $_[0]->{stopped} or @{$_[0]->{in}} }
# reset the state machine
sub reset
{
my $self = shift;
$self-> cancel_all_events;
@{$self-> {last}} = ();
delete $self-> {stopped};
warn _d( $self, 'reset') if $DEBUG_LAMBDA;
}
# start the state machine
sub start
{
my $self = shift;
confess "can't start active lambda, call reset() first" if $self-> is_active;
warn _d( $self, 'started') if $DEBUG_LAMBDA;
@{$self->{last}} = $self-> {start}-> ($self, @{$self->{last}})
if $self-> {start};
warn $self-> _msg('initial') if $DEBUG_LAMBDA;
unless ( @{$self->{in}}) {
warn _d( $self, 'stopped') if $DEBUG_LAMBDA;
$self-> {stopped} = 1;
}
}
# peek into the current state
sub peek { wantarray ? @{$_[0]->{last}} : $_[0]-> {last}-> [0] }
# pass initial parameters to lambda
sub call
{
my $self = shift;
confess "can't call active lambda" if $self-> is_active;
@{$self-> {last}} = @_;
$self;
}
# abandon all states and stop with constant message
sub terminate
{
my ( $self, @error) = @_;
$self-> {last} = \@error;
$self-> cancel_all_events;
warn $self-> _msg('terminate') if $DEBUG_LAMBDA;
}
# propagate event destruction on all levels
sub destroy
{
shift-> cancel_all_events( cascade => 1);
}
# synchronisation
# drives objects dependant on the other objects until all of them
# are stopped
my ($drive_reentrancy_refresh, $drive_reentrancy_depth) = (0,0);
sub drive
{
$drive_reentrancy_depth++;
my $changed = 1;
my $executed = 0;
warn "IO::Lambda::drive --------\n" if $DEBUG_LAMBDA;
eval {
while ( $changed) {
$changed = 0;
# dispatch
for my $rec ( map { @$_ } values %EVENTS) {
next unless $rec->[WATCH_LAMBDA]-> {stopped};
$changed = 1;
$executed++;
$rec->[WATCH_OBJ]-> lambda_handler( $rec);
$drive_reentrancy_refresh = 0, last if $drive_reentrancy_refresh;
}
warn "IO::Lambda::drive .........\n" if $DEBUG_LAMBDA and $changed;
}
};
die $@ if $@;
warn "IO::Lambda::drive +++++++++\n" if $DEBUG_LAMBDA;
$drive_reentrancy_depth--;
$drive_reentrancy_refresh++ if $executed && $drive_reentrancy_depth;
return $executed;
}
# do one quant
sub yield
{
my $nonblocking = shift;
my $more_events = 0;
# custom loops must not wait
for ( @LOOPS) {
next if $_-> empty;
$_-> yield;
$more_events = 1;
}
if ( drive) {
# some callbacks we called, don't let them wait in sleep
return 1;
}
# main loop waits, if anything
unless ( $LOOP-> empty) {
$LOOP-> yield( $nonblocking);
$more_events = 1;
( run in 0.906 second using v1.01-cache-2.11-cpan-99c4e6809bf )