The easiest way to broadcast events is to fire a shotgun at POE and see what gets hit. The shotgun "shell" is a fictitious signal posted with POE::Kernel's signal() method.

Because a signal is propagated to a session's children, and every session is a child of POE::Kernel, this line of code will broadcast a fake signal to every session:

$kernel->signal($kernel, 'FakeSignal', @parameters);

The signal is dispatched as a signal event by default. ARG0 contains "FakeSignal" so sessions know what they've received, and ARG1..$# hold @parameters.

It's possible to aim the shotgun in a general direction with POE::Kernel's sig() method. This tells POE that the calling session wants to receive "FakeSignal" signals as "fake_signal" events rather than generic "_signal" events.

$kernel->sig(FakeSignal => "fake_signal");

Each session must call sig() to rename signals for itself. ARG0 and ARG1..$#_ will hold the same values as before.


A registry can enable sessions to request broadcasted events. When sessions start, they add themselves to a global hash. They remove themselves at stop time. Finally, a broadcast() function sends events to every session in the registry.

my %session_registry;
POE::Session->create(
  inline_states => {
    ...,
    _start => sub {
      ...;

      # Register here.
      $session_registry{$_[SESSION]->ID()} = $_[SESSION]->ID();
      ...;
    },
    _stop => sub {
      ...;

      # Unregister here.
      delete $session_registry{$_[SESSION]->ID()};
      ...;
    },
    ...,
  },
);

# Send an event to every registered session.
sub broadcast {
  my ($event, @etc) = @_;
  foreach (keys %session_registry) {
    $poe_kernel->post($_, $event, @etc);
  }
}

The idea can be refined to provide several "channels":

my $session_registry;
my $session_id = $_[SESSION]->ID();
$session_registry{channel_name}->{$session_id} = $session_id;
delete $session_registry{channel_name}->{$session_id};

# Send an event to every session in a channel.
sub broadcast {
  my ($channel, $event, @etc) = @_;
  foreach (keys %{$session_registry{$channel}}) {
    $poe_kernel->post($_, $event, @etc);
  }
}

And so on.


Maybe it should be a component?

Fletch chimes in . . .

This is very similar to the [ObserverPattern]. Of course I just read Design Patterns recently so I may just have patterns on the brane. :)

At any rate, it might make sense to define some sort of Component::BroadcastGroup. Each group would have its own alias, and register, unregister, and notify events. That seems cleaner to me than shoehorning onto the signal framework or using a lexical structure.


Apocalypse notices something...

This is very similar to POE::Component::SimpleLog, which uses the same register/unregister concepts found here :)