++ed by:

1 non-PAUSE user.

Author image Toshio Ito


Async::Selector::Aggregator - aggregator of watchers and other aggregators




    use Async::Selector;
    use Async::Selector::Aggregator;
    ## Setup resources with 3 selectors, each of which registers 'resource'
    my %resources = (
        a => { val => 0, selector => Async::Selector->new },
        b => { val => 0, selector => Async::Selector->new },
        c => { val => 0, selector => Async::Selector->new },
    foreach my $res (values %resources) {
        $res->{selector}->register(resource => sub {
            my ($threshold) = @_;
            return $res->{val} >= $threshold ? $res->{val} : undef;
    ## Aggregate 3 selectors into one. Resource names are now ('a', 'b', 'c')
    sub aggregate_watch {
        my $callback = pop;
        my %watch_spec = @_;
        my $aggregator = Async::Selector::Aggregator->new();
        foreach my $key (keys %watch_spec) {
            my $watcher = $resources{$key}{selector}->watch(
                resource => $watch_spec{$key}, sub {
                    my ($w, %res) = @_;
                    $callback->($aggregator, $key => $res{resource});
            last if !$aggregator->active;
        return $aggregator;
    ## Treat 3 selectors like a single selector almost transparently.
    ## $w and $watcher are actually an Async::Selector::Aggregator.
    my $watcher = aggregate_watch(a => 3, b => 0, sub {
        my ($w, %res) = @_;
        handle_a($res{a}) if exists $res{a};
        handle_b($res{b}) if exists $res{b};
    ## In this case, the callback is called immediately and $w->cancel is called.
    $watcher->active;  ## => false


Async::Selector::Aggregator is an object that keeps Async::Selector::Watcher objects and/or other aggregator objects and treats them as a single watcher. Using Async::Selector::Aggregator, you can ensure that a certain set of watchers are always cancelled at the same time. This is useful when you use multiple Async::Selectors and treat them as a single selector.

Watchers and aggregators kept in an Async::Selector::Aggregator are in one of the two states; they are all active or they are all inactive. No intermediate state is possible unless you call cancel() method on individual watchers. You should not cancel individual watchers once you aggregate them into an Async::Selector::Aggregator object.


$aggregator = Async::Selector::Aggregator->new()

Creates a new Async::Selector::Aggregator object. It takes no argument.

A newly created aggregator is active.



Adds the given $watcher to the $aggregator. The $watcher may be an Async::Selector::Watcher object or an Async::Selector::Aggregator object.

If $aggregator is active and $watcher is inactive, $aggregator->cancel() is automatically called. If $aggregator is inactive and $watcher is active, $watcher->cancel() is automatically called. This is because all watchers in the $aggregator must share the same state.

If $watcher is the same instance as $aggregator, it croaks.

@watchers = $aggregator->watchers()

Returns the list of all watchers kept in the $aggregator.

$is_active = $aggregator->active()

Returns true if the $aggregator is active. Returns false otherwise.


Cancels the $aggregator, that is, changes its state into inactive. This method also cancels all watchers kept in the $aggregator.


Toshio Ito <toshioito at cpan.org>