The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
NAME
    MooX::Role::POE::Emitter - Pluggable POE event emitter role for cows

SYNOPSIS
      ## A POE::Session that can broadcast events to listeners:
      package My::EventEmitter;

      use POE;
      use Moo;
      with 'MooX::Role::POE::Emitter';

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

        $self->set_object_states(
          [
            $self => {
              ## Add some extra handlers to your Emitter
              'emitter_started' => '_emitter_started',
            },

            ## Include any object_states we had previously
            ## (e.g. states added at construction time)
            (
              $self->has_object_states ?
                @{ $self->object_states } : ()
            ),

            ## Maybe include from named arguments, for example:
            (
              ref $args{object_states} eq 'ARRAY' ?
                @{ $args{object_states } : ()
            ),
          ],
        );

        ## Start our Emitter's POE::Session:
        $self->_start_emitter;
      }

      sub shutdown {
        my ($self) = @_;
        $self->_shutdown_emitter;
      }

      sub _emitter_started {
        my ($kernel, $self) = @_[KERNEL, OBJECT];
        ## A POE state called when the emitter's session starts.
        ## (Analogous to a normal '_start' handler)
        ## Could load plugins, do initialization, etc.
      }

      ## A listening POE::Session:
      package My::Listener;
      use POE;

      sub spawn {
        my ($self, $alias_or_sessionID) = @_;

        POE::Session->create(
          ## Set up a Session, etc
          object_states => [
            $self => [
                'emitted_my_event',
                . . .
            ],
          ],
        );

        ## Subscribe to all events from $alias_or_sessionID
        $poe_kernel->post(
          $alias_or_sessionID,
          'subscribe',
          'all'
        );
      }

      sub emitted_my_event {
        my ($kernel, $self) = @_[KERNEL, OBJECT];
        ## Received 'my_event' from Emitter
      }

DESCRIPTION
    A Moo::Role for a POE Observer Pattern implementation.

    Consuming this role gives your class a POE::Session capable of
    processing events via loaded plugins and/or emitting them to registered
    "listener" sessions.

    It is derived from POE::Component::Syndicator by BINGOS, HINRIK, APOCAL
    et al, but with more cows ;-) and a few extra features (such as
    anonymous coderef callbacks; see "yield"), as well as the faster plugin
    dispatch system that comes with MooX::Role::Pluggable.

    The Emitter role consumes MooX::Role::Pluggable, making your emitter
    pluggable (see the MooX::Role::Pluggable documentation for
    plugin-related details).

    You do not need to create your own POE::Session; calling
    "_start_emitter" will spawn one for you. You also get some useful sugar
    over POE event dispatch (such as anonymous coderef callbacks); see
    "Methods".

  Creating an Emitter
    "SYNOPSIS" contains an emitter that uses set_$attrib methods to
    configure itself when "spawn()" is called; these attribs can, of course,
    be set when your Emitter is constructed:

      my $emitter = MyEmitter->new(
        alias => 'my_emitter',
        pluggable_type_prefixes => {
          NOTIFY  => 'Notify',
          PROCESS => 'Proc',
        },
        # . . .
      );

   Attributes
    Most of these can be altered via set_$attrib methods at any time before
    "_start_emitter" is called.

   alias
    alias specifies the POE::Kernel alias used for our POE::Session;
    defaults to the stringified object.

    Set via set_alias -- if the Emitter is running, a prefixed alias_set
    event is emitted.

   event_prefix
    event_prefix is prepended to notification events before they are
    dispatched to listening sessions. It is also used for the plugin
    pipeline's internal events; see "_pluggable_event" in
    MooX::Role::Pluggable for details.

    Defaults to *emitted_*

    Set via set_event_prefix

   pluggable_type_prefixes
    pluggable_type_prefixes is a hash reference that can optionally be set
    to change the default MooX::Role::Pluggable plugin handler prefixes for
    "PROCESS" and "NOTIFY" (which default to "P" and "N", respectively):

      my $emitter = $class->new(
        pluggable_type_prefixes => {
          PROCESS => 'P',
          NOTIFY  => 'N',
        },
      );

    Set via set_pluggable_type_prefixes

   object_states
    object_states is an array reference suitable for passing to
    POE::Session; the subclasses own handlers should be added to
    object_states prior to calling "_start_emitter".

    Set via set_object_states

   register_prefix
    register_prefix is prepended to 'register' and 'unregister' methods
    called on plugins at load time (see MooX::Role::Pluggable).

    Defaults to *Emitter_*

    Set via set_register_prefix

   session_id
    session_id is our emitter's POE::Session ID, set when our Session is
    started via "_start_emitter".

   _start_emitter
    _start_emitter() should be called on our object to spawn the actual
    POE::Session. It takes no arguments and should be called after the
    object has been configured.

   _shutdown_emitter
    _shutdown_emitter() must be called to terminate the Emitter's
    POE::Session

    A 'shutdown' event will be emitted before sessions are dropped.

  Listening sessions
   Session event subscription
    An external POE::Session can subscribe to receive events via normal POE
    event dispatch by sending a "subscribe":

      $poe_kernel->post( $emitter->session_id,
        'subscribe',
        @events
      );

    Listening sessions are consumers; they cannot modify event arguments in
    any meaningful way, and will receive arguments as-normal (in @_[ARG0 ..
    $#_] like any other POE state). Plugins operate differently and receive
    references to arguments that can be modified -- see
    MooX::Role::Pluggable for details.

   Session event unregistration
    An external Session can unregister subscribed events using the same
    syntax as above:

      $poe_kernel->post( $emitter->session_id,
        'unsubscribe',
        @events
      );

  Receiving events
   Events delivered to listeners
    Events are delivered to subscribed listener sessions as normal POE
    events, with the configured "event_prefix" prepended and arguments
    available via @_[ARG0 .. $#_] as normal.

      sub emitted_my_event {
        my ($kernel, $self) = @_[KERNEL, OBJECT];
        my @args = @_[ARG0 .. $#_];
        # . . .
      }

    See "Session event subscription" and "emit"

   Events delivered to this session
    The emitter's POE::Session provides a '_default' handler that
    redispatches unknown POE-delivered events to "process" (except for
    events prefixed with '_', which are reserved).

    You can change this behavior by overriding '_emitter_default' -- here's
    a direct adaption of the example from POE::Component::Syndicator:

      use Moo;
      use POE;
      with 'MooX::Role::POE::Emitter';
      around '_emitter_default' => sub {
        my $orig = shift;
        my ($kernel, $self) = @_[KERNEL, OBJECT];
        my ($event, $args)  = @_[ARG0, ARG1];

        ## process(), then do something else, for example
        return if $self->process( $event, @$args ) == EAT_ALL;

        . . .
      };

    (Note that due to internal redispatch $_[SENDER] will be the Emitter's
    Session.)

  EAT values
    MooX::Role::Pluggable uses "EAT_*" constants to indicate event lifetime.

    If a plugin in the pipeline returns EAT_CLIENT or EAT_ALL, events are
    not dispatched to subscribed listening sessions; a dispatched NOTIFY
    event goes to your emitter's Session if it is subscribed to receive it,
    then to the plugin pipeline, and finally to other subscribed listener
    Sessions unless a plugin returned EAT_CLIENT or EAT_ALL.

    See "emit" for more on dispatch behavior and event lifetime. See
    MooX::Role::Pluggable for details regarding plugins.

   NOTIFY events
    NOTIFY events are intended to be dispatched asynchronously to our own
    session, any loaded plugins in the pipeline, and subscribed listening
    sessions, respectively.

    See "emit".

   PROCESS events
    PROCESS events are intended to be processed by the plugin pipeline
    immediately; these are intended for message processing and similar
    synchronous action handled by plugins.

    Handlers for PROCESS events are prefixed with "P_"

    See "process".

  Sending events
   emit
      $self->emit( $event, @args );

    emit() dispatches "NOTIFY events" -- these events are dispatched first
    to our own session (with "event_prefix" prepended), then any loaded
    plugins in the pipeline (with "N_" prepended), then registered sessions
    (with "event_prefix" prepended):

      ## With default event_prefix:
      $self->emit( 'my_event', @args )
      #  -> Dispatched to own session as 'emitted_my_event'
      #  -> Dispatched to plugin pipeline as 'N_my_event'
      #  -> Dispatched to registered sessions as 'emitted_my_event'
      #     *unless* a plugin returned EAT_CLIENT or EAT_ALL

    See "Receiving events", "EAT values"

   emit_now
      $self->emit_now( $event, @args );

    emit_now() synchronously dispatches "NOTIFY events" -- see "emit".

   process
      $self->process( $event, @args );

    process() calls registered plugin handlers for "PROCESS events"
    immediately; these are not dispatched to listening sessions.

    See MooX::Role::Pluggable for details on pluggable event dispatch.

  Methods
    These methods provide easy proxy mechanisms for issuing POE events and
    managing timers within the context of the emitter's POE::Session.

   yield
      $self->yield( $poe_event, @args );

    Provides an interface to POE::Kernel's yield/post() method, dispatching
    POE events within the context of the emitter's session.

    The event can be either a named event/state dispatched to your Emitter's
    POE::Session:

      $emitter->yield( 'some_event', @args );

    ... or an anonymous coderef, which is executed as if it were a named POE
    state belonging to your Emitter:

      $emitter->yield( sub {
        ## $_[OBJECT] is the Emitter's object:
        my ($kernel, $self) = @_[KERNEL, OBJECT];
        my @params          = @_[ARG0 .. $#_];

        ## $_[STATE] is the current coderef
        ## Yield ourselves again, for example:
        $self->yield( $_[STATE], @new_args )
          if $some_condition;
      }, $some, $args );

    Inside an anonymous coderef callback such as shown above, $_[OBJECT] is
    the Emitter's $self object and $_[STATE] contains the callback coderef
    itself.

   call
      $self->call( $poe_event, @args );

    The synchronous counterpart to "yield".

   timer
      my $alarm_id = $self->timer(
        $delayed_seconds,
        $event,
        @args
      );

    Set a timer in the context of the emitter's POE::Session. Returns the
    POE alarm ID.

    The event can be either a named event/state or an anonymous coderef (see
    "yield").

    A prefixed ("event_prefix") 'timer_set' event is emitted when a timer is
    set. Arguments are the alarm ID, the event name or coderef, the delay
    time, and any event parameters, respectively.

   timer_del
      $self->timer_del( $alarm_id );

    Clears a pending "timer".

    A prefixed ("event_prefix") 'timer_deleted' event is emitted when a
    timer is deleted. Arguments are the removed alarm ID, the event name or
    coderef, and any event parameters, respectively.

  Moose compatibility
    This Role "seems to be" Moose-compatible as of version 0.07, but you'll
    need to consume MooX::Role::Pluggable on its own, as far as I can tell:

      package MyEmitter;
      use Moose;
      with 'MooX::Role::Pluggable', 'MooX::Role::POE::Emitter';

SEE ALSO
    For details regarding POE, see POE, POE::Kernel, POE::Session

    For details regarding Moo classes and Roles, see Moo, Moo::Role,
    Role::Tiny

AUTHOR
    Jon Portnoy <avenj@cobaltirc.org>

    Derived from POE::Component::Syndicator-0.06 by BINGOS, HINRIK, APOCAL
    et al. That will probably do you for non-Moo(se) use cases; I needed
    something cow-like that worked with MooX::Role::Pluggable.

    Licensed under the same terms as perl5