Beam-Emitter

 view release on metacpan or  search on metacpan

lib/Beam/Emitter.pm  view on Meta::CPAN

#pod     extends 'Beam::Event';
#pod
#pod     has who => (
#pod         is => 'ro',
#pod         required => 1,
#pod     );
#pod
#pod Now that we can represent who is knocking, let's notify our subscribers.
#pod
#pod     package Door;
#pod     use Moo;
#pod     use Door::Knock; # Our emitter must load the class, Beam::Emitter will not
#pod     with 'Beam::Emitter';
#pod
#pod     sub open {
#pod         my ( $self, $who ) = @_;
#pod         my $event = $self->emit( 'before_open', class => 'Door::Knock', who => $who );
#pod         return if $event->is_default_stopped;
#pod         $self->open_the_door;
#pod     }
#pod
#pod Finally, let's build a listener that knows who is allowed in the door.
#pod
#pod     my $private_door = Door->new;
#pod     $private_door->on( before_open => sub {
#pod         my ( $event ) = @_;
#pod
#pod         if ( $event->who ne 'preaction' ) {
#pod             $event->stop_default;
#pod         }
#pod
#pod     } );
#pod
#pod     $private_door->open;
#pod
#pod =head2 Without Beam::Event
#pod
#pod Although checking C<is_default_stopped> is completely optional, if you do not
#pod wish to use the C<Beam::Event> object, you can instead call L<emit_args>
#pod instead of L<emit> to give arbitrary arguments to your listeners.
#pod
#pod     package Door;
#pod     use Moo;
#pod     with 'Beam::Emitter';
#pod
#pod     sub open {
#pod         my ( $self, $who ) = @_;
#pod         $self->emit_args( 'open', $who );
#pod         $self->open_the_door;
#pod     }
#pod
#pod There's no way to stop the door being opened, but you can at least notify
#pod someone before it does.
#pod
#pod =head1 SEE ALSO
#pod
#pod =over 4
#pod
#pod =item L<Beam::Event>
#pod
#pod =item L<Beam::Emitter::Cookbook>
#pod
#pod This document contains some useful patterns for your event emitters and
#pod listeners.
#pod
#pod =item L<http://perladvent.org/2013/2013-12-16.html>
#pod
#pod Coordinating Christmas Dinner with Beam::Emitter by Yanick Champoux.
#pod
#pod =back
#pod
#pod =cut

use strict;
use warnings;

use Types::Standard qw(:all);
use Scalar::Util qw( weaken refaddr );
use Carp qw( croak );
use Beam::Event;
use Module::Runtime qw( use_module );
use Moo::Role; # Put this last to ensure proper, automatic cleanup


# The event listeners on this object, a hashref of arrayrefs of
# EVENT_NAME => [ Beam::Listener object, ... ]

has _listeners => (
    is      => 'ro',
    isa     => HashRef,
    default => sub { {} },
);

#pod =method subscribe ( event_name, subref, [ %args ] )
#pod
#pod Subscribe to an event from this object. C<event_name> is the name of the event.
#pod C<subref> is a subroutine reference that will get either a L<Beam::Event> object
#pod (if using the L<emit> method) or something else (if using the L<emit_args> method).
#pod
#pod Returns a coderef that, when called, unsubscribes the new subscriber.
#pod
#pod     my $unsubscribe = $emitter->subscribe( open_door => sub {
#pod         warn "ding!";
#pod     } );
#pod     $emitter->emit( 'open_door' );  # ding!
#pod     $unsubscribe->();
#pod     $emitter->emit( 'open_door' );  # no ding
#pod
#pod This unsubscribe subref makes it easier to stop our subscription in a safe,
#pod non-leaking way:
#pod
#pod     my $unsub;
#pod     $unsub = $emitter->subscribe( open_door => sub {
#pod         $unsub->(); # Only handle one event
#pod     } );
#pod     $emitter->emit( 'open_door' );
#pod
#pod The above code does not leak memory, but the following code does:
#pod
#pod     # Create a memory cycle which must be broken manually
#pod     my $cb;

lib/Beam/Emitter.pm  view on Meta::CPAN

    # add metadata with subscription time
    has sub_time => is ( 'ro',
			  init_arg => undef,
			  default => sub { time() },
    );
  }

  # My::Emitter consumes the Beam::Emitter role
  my $emitter = My::Emitter->new;
  $emitter->on( "foo",
    sub { print "Foo happened!\n"; },
   class => MyListener
  );

The L</listeners> method can be used to examine the subscribed listeners.

=head2 on ( event_name, subref )

An alias for L</subscribe>. B<NOTE>: Do not use this alias for method
modifiers! If you want to override behavior, override C<subscribe>.

=head2 unsubscribe ( event_name [, subref ] )

Unsubscribe from an event. C<event_name> is the name of the event. C<subref> is
the single listener subref to be removed. If no subref is given, will remove
all listeners for this event.

=head2 un ( event_name [, subref ] )

An alias for L</unsubscribe>. B<NOTE>: Do not use this alias for method
modifiers! If you want to override behavior, override C<unsubscribe>.

=head2 emit ( name, event_args )

Emit a L<Beam::Event> with the given C<name>. C<event_args> is a list of name => value
pairs to give to the C<Beam::Event> constructor.

Use the C<class> key in C<event_args> to specify a different Event class.

=head2 emit_args ( name, callback_args )

Emit an event with the given C<name>. C<callback_args> is a list that will be given
directly to each subscribed callback.

Use this if you want to avoid using L<Beam::Event>, though you miss out on the control
features like L<stop|Beam::Event/stop> and L<stop default|Beam::Event/stop_default>.

=head2 listeners ( event_name )

Returns a list containing the listeners which have subscribed to the
specified event from this emitter.  The list elements are either
instances of L<Beam::Listener> or of custom classes specified in calls
to L</subscribe>.

=head1 SEE ALSO

=over 4

=item L<Beam::Event>

=item L<Beam::Emitter::Cookbook>

This document contains some useful patterns for your event emitters and
listeners.

=item L<http://perladvent.org/2013/2013-12-16.html>

Coordinating Christmas Dinner with Beam::Emitter by Yanick Champoux.

=back

=head1 AUTHOR

Doug Bell <preaction@cpan.org>

=head1 CONTRIBUTORS

=for stopwords Diab Jerius Joel Berger Yanick Champoux

=over 4

=item *

Diab Jerius <djerius@cfa.harvard.edu>

=item *

Joel Berger <joel.a.berger@gmail.com>

=item *

Yanick Champoux <yanick@babyl.dyndns.org>

=back

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by Doug Bell.

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

=cut



( run in 1.499 second using v1.01-cache-2.11-cpan-39bf76dae61 )