AnyEvent-Callback
view release on metacpan or search on metacpan
lib/AnyEvent/Callback.pm view on Meta::CPAN
} => __PACKAGE__;
$self;
}
sub CBS {
return AnyEvent::Callback::Stack->new;
}
=head2 error
Calls error callback. If the object has no registered error callbacks,
parent object's error callback will be called.
$cb->error('WTF?');
=cut
sub error {
my ($self, @error) = @_;
$self->{ecalled}++;
carp "Repeated error callback calling: $self->{ecalled}"
if $self->{ecalled} > 1;
carp "Calling error callback after result callback"
if $self->{called};
if ($self->{ecb}) {
$self->{ecb}( @error );
delete $self->{ecb};
delete $self->{cb};
delete $self->{parent};
return;
}
delete $self->{ecb};
delete $self->{cb};
my $parent = delete $self->{parent};
unless($parent) {
carp "Uncaught error: @error";
return;
}
$parent->error( @error );
return;
}
sub DESTROY {
my ($self) = @_;
return if $self->{called} or $self->{ecalled};
$self->error("no one touched registered callback");
delete $self->{cb};
delete $self->{ecb};
}
package AnyEvent::Callback::Stack;
use Scalar::Util 'weaken';
use Carp;
sub new {
my ($class) = @_;
return bless { stack => [], done => 0 } => ref($class) || $class;
}
sub cb {
my ($self) = @_;
my $idx = @{ $self->{stack} };
my $cb = AnyEvent::Callback::CB
sub {
$self->{stack}[$idx] = AnyEvent::Callback::Stack::Result->new(@_);
$self->{done}++;
$self->_check_if_done;
},
sub {
$self->{stack}[$idx] = AnyEvent::Callback::Stack::Result->err(@_);
$self->{done}++;
$self->_check_if_done;
}
;
push @{ $self->{stack} } => $cb;
weaken $self->{stack}[$idx];
return $self->{stack}[$idx];
}
sub _check_if_done {
my ($self) = @_;
return unless $self->{waiter};
return unless $self->{done} >= @{ $self->{stack} };
my $cb = delete $self->{waiter};
$cb->(@{ $self->{stack} });
$self->{stack} = [];
$self->{done} = 0;
}
sub wait :method {
my ($self, $cb) = @_;
croak 'Usage: $cbs->wait(sub { ... })' unless 'CODE' eq ref $cb;
croak 'You have already initiated wait process' if $self->{waiter};
$self->{waiter} = $cb;
$self->_check_if_done;
}
package AnyEvent::Callback::Stack::Result;
sub new {
my ($class, @res) = @_;
return bless { res => \@res } => ref($class) || $class;
}
sub err {
my ($class, @res) = @_;
return bless { err => \@res, res => [] } => ref($class) || $class;
}
sub is_error {
my ($self) = @_;
return exists $self->{err};
}
sub results {
my ($self) = @_;
return $self->{res} unless wantarray;
return @{ $self->{res} };
}
sub errors {
my ($self) = @_;
return unless $self->is_error;
return $self->{err} unless wantarray;
return @{ $self->{err} };
}
sub errstr {
my ($self) = @_;
return join ' ' => $self->errors;
}
=head1 COPYRIGHT AND LICENCE
Copyright (C) 2012 by Dmitry E. Oboukhov
( run in 2.947 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )