AnyEvent-Blackboard

 view release on metacpan or  search on metacpan

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

use warnings FATAL => "all";

use AnyEvent;
use parent qw( Async::Blackboard );
use Carp qw( croak confess );

our $VERSION = "0.4.10";

=head1 ATTRIBUTES

=over 4

=cut

=item default_timeout -> Num

Default timeout in (optionally fractional) seconds.

=cut

=item condvar -> AnyEvent::CondVar

A conditional variable to track dispatches. (optional)

When supplied, each dispatch group will be wrapped in calls to ``begin'' and
``end'' on condvar instance.

=cut

sub new {
    my ($class, @arguments) = @_;

    if (@arguments % 2) {
        croak "AnyEvent::Blackboard->new() requires a balanced list";
    }

    my %options = @arguments;

    my $self = $class->SUPER::new();

    @$self{qw( -default_timeout -condvar )} =
        @options{qw( default_timeout condvar )};

    $self->{-condvar} //= AnyEvent->condvar;

    return $self;
}

=back

=cut

=back

=head1 METHODS

=over 4

=item timeout SECONDS, [ KEY, [, DEFAULT ] ]

Set a timer for N seconds to provide "default" value as a value, defaults to
`undef`.  This can be used to ensure that blackboard workflows do not reach a
dead-end if a required value is difficult to obtain.

=cut

sub timeout {
    my ($self, $seconds, $key, $default) = @_;

    $key = [ $key ] unless (ref $key eq "ARRAY");

    unless ($self->has($key)) {
        my $guard = AnyEvent->timer(
            after => $seconds,
            cb    => sub {
                unless ($self->has($key)) {
                    $self->put($_ => $default) for @$key;
                }
            }
        );

        # Cancel the timer if we find the object first (otherwise this is a NOOP).
        $self->_watch($key, sub { undef $guard });
    }
}

=item watch KEYS, WATCHER [, KEYS, WATCHER ]

=item watch KEY, WATCHER [, KEYS, WATCHER ]

Overrides L<Async::Blackboard> only for the purpose of adding a timeout.

=cut

sub watch {
    my ($self, @args) = @_;

    confess "Expected balanced as arguments" if @args % 2;

    my $timeout = $self->{-default_timeout};

    if ($timeout) {
        my $i = 0;

        for my $key (grep $i++ % 2 == 0, @args) {
            $self->timeout($timeout, $key);
        }
    }

    $self->SUPER::watch(@args);
}

=item found KEY

Wrap calls to ``found'' in condvar transaction counting, if a condvar is
supplied.  The side-effect is that dispatching is wrapped in conditional
variable counting.

=cut

sub found {
    my ($self, @args) = @_;

    if ($self->has_condvar) {
        my $condvar = $self->condvar;

        $condvar->begin;

        $self->SUPER::found(@args);

        $condvar->end;
    }
    else {
        $self->SUPER::found(@args);
    }
}

=item clone

Create a clone of this blackboard.  This will not dispatch any events, even if
the blackboard is prepopulated.



( run in 0.801 second using v1.01-cache-2.11-cpan-437f7b0c052 )