# NAME

Object::Pad::Role::EventEmitter - A role for Object::Pad classes to emit events

# SYNOPSIS

    use Object::Pad;
    use Object::Pad::Role::EventEmitter;

    package MyObject;
    class MyObject :does(Object::Pad::Role::EventEmitter);

    method foo($a) {
      $self->emit(foo => $a);
    }

    1;

    package main;

    use MyObject;
    use Future;
    use Future::Queue;

    my $i = MyObject->new;

    # subscribe to an event once:
    $i->once(foo => sub { say "Hello" });

    # or with a future:
    my $f = Future->new->on_done(sub { say "Hello" });
    $i->on(foo => $f);

    # subscribe to multiple events:
    my $subscription = $i->on(foo => sub { say "Hello" });

    # or on a queue:
    my $q = Future::Queue->new;
    my $subscription_q = $i->on(foo => $q);

    # then unsubscribe:
    $i->unsubscribe( $subscription );
    $i->unsubscribe( $subscription_q );

    # or finish the queue (unsubscribes upon the next event):
    $q->finish;

# DESCRIPTION

This role adds to a class the capability to emit events to subscribers.
Interested subscribers can provide a code reference, a [Future::Queue](https://metacpan.org/pod/Future%3A%3AQueue)
or a [Future](https://metacpan.org/pod/Future) to receive events.

# METHODS

## on

    my $subscription = $obj->on( foo => sub { ... } );
    my $subscription = $obj->on( foo => $f );
    my $subscription = $obj->on( foo => $q);

Subscribes to notifications of the named event.  The event consumer can be
a coderef, [Future](https://metacpan.org/pod/Future) or [Future::Queue](https://metacpan.org/pod/Future%3A%3AQueue). In case it's a `Future`, the
consumer will be unsubscribed after a single event.

Returns a `$subscription` which can be used to unsubscribe later.

## once

    my $subscription = $obj->once( foo => sub { ... } );

Subscribes to a single notification of teh named event.  This function does
not make sense for the Future and Future::Queue subscribers, because Futures
are single-notification anyway and Future::Queues are much more easily
replaced with Futures for single notifications.

## emit

    $obj->emit( $event_name, $arg1, $arg2, ...)

Send the event to subscribers.  If the subscriber is a coderef, the
function is called with the object as the first argument and the values
of `$arg1, $arg2, ...` as further arguments.  If the subscriber is a
Future, it resolves with the same values as passed to the callback.  If
the subscriber is a Future::Queue, an arrayref is put in the queue with
the elements of the array being the values as passed to the callback.

    # callback style:
    $sink->( $obj, $arg1, $arg2, ... );

    # Future style:
    $f->done( $obj, $arg1, $arg2, ... );

    # Future::Queue style:
    $q->push( [ $obj, $arg1, $arg2, ... );

## has\_subscribers

    my $bool = $obj->has_subscribers( 'foo' );

Checks if the named event has subscribers.

## unsubscribe

    $obj->unsubscribe( 'foo' );
    $obj->unsubscribe( foo => $subscription );

Remove all subscribers from the named event (when no subscription argument
is given) or remove the specific subscription.

Any pending futures will be cancelled upon unsubscription.  Queues will
be finished.

When an object goes out of scope, this function is used to cancel any active
subscriptions.

# AUTHOR

- `Erik Huelsmann <ehuels@gmail.com>`

Inspired on [Role::EventEmitter](https://metacpan.org/pod/Role%3A%3AEventEmitter) by Dan Book, which is itself adapted
from [Mojolicious](https://metacpan.org/pod/Mojolicious).  This module and its tests are implemented from scratch.

# COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by Erik Huelsmann.

This is free software; you can redistribute it and/or modify it under the same
terms as the Perl 5 programming language system itself.
