AnyEvent-Callback

 view release on metacpan or  search on metacpan

lib/AnyEvent/Callback.pm  view on Meta::CPAN

            ...
            yet_another_watcher1 $cb->CB( sub {
                my $cb = pop;
                ...
                $cb->( 123 );   # upwards callback

            });
            yet_another_watcher2 $cb->CB( sub {
                my $cb = pop;
                ...

                $cb->error( 456 );  # on_error will be called

            });
        });
    }


=head1 METHODS

=head2 'CODE' (overloaded fake method)

    $cb->( ... );

You can use the object as usually B<CODEREF>.

=cut

use overload
    '&{}' => sub {
        my ($self) = shift;
        sub {
            $self->{called}++;
            carp "Repeated callback calling: $self->{called}"
                if $self->{called} > 1;
            carp "Calling result callback after error callback"
                if $self->{ecalled};
            $self->{cb}->(@_) if $self->{cb};
            delete $self->{cb};
            delete $self->{ecb};
            delete $self->{parent};
            return;
        };
    },
    bool => sub { 1 } # for 'if ($cb)'
;


=head2 CB

Creates new callback object that have binding on parent callback.

    my $new_cb = $cb->CB(sub { ... });   # the cb doesn't catch errors

    my $new_cb = CB(sub { ... }, sub { ... }); # the cb catches errors

    my $new_cb = $cb->CB(sub { ... }, sub { ... }); # the same

=cut

sub CB(&;&) {

    my $parent;
    my ($cb, $ecb) = @_;

    ($parent, $cb, $ecb) = @_ unless 'CODE' eq ref $cb;

    croak 'Callback must be CODEREF' unless 'CODE' eq ref $cb;
    croak 'Error callback must be CODEREF or undef'
        unless 'CODE' eq ref $ecb or !defined $ecb;

    # don't translate erorrs upwards if error callback if exists
    $parent = undef if $ecb;

    my $self = bless {
        cb      => $cb,
        ecb     => $ecb,
        parent  => $parent,
        called  => 0,
        ecalled => 0,
    } => __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) {



( run in 0.370 second using v1.01-cache-2.11-cpan-5a3173703d6 )