# A simple POE Component that sends ping events to registered sessions
# and plugins every second.
{
package SimplePoCo;
use strict;
use warnings;
use base qw(POE::Component::Pluggable);
use POE;
use POE::Component::Pluggable::Constants qw(:ALL);
sub spawn {
my ($package, %opts) = @_;
my $self = bless \%opts, $package;
$self->_pluggable_init(
prefix => 'simplepoco_',
types => [qw(EXAMPLE)],
debug => 1,
);
POE::Session->create(
object_states => [
$self => { shutdown => '_shutdown' },
$self => [qw(_send_ping _start register unregister __send_event)],
],
);
return $self;
}
sub shutdown {
my ($self) = @_;
$poe_kernel->post($self->{session_id}, 'shutdown');
}
sub _pluggable_event {
my ($self) = @_;
$poe_kernel->post($self->{session_id}, '__send_event', @_);
}
sub _start {
my ($kernel, $self) = @_[KERNEL, OBJECT];
$self->{session_id} = $_[SESSION]->ID();
if ($self->{alias}) {
$kernel->alias_set($self->{alias});
}
else {
$kernel->refcount_increment($self->{session_id}, __PACKAGE__);
}
$kernel->delay(_send_ping => $self->{time} || 300);
return;
}
sub _shutdown {
my ($kernel, $self) = @_[KERNEL, OBJECT];
$self->_pluggable_destroy();
$kernel->alarm_remove_all();
$kernel->alias_remove($_) for $kernel->alias_list();
$kernel->refcount_decrement($self->{session_id}, __PACKAGE__) if !$self->{alias};
$kernel->refcount_decrement($_, __PACKAGE__) for keys %{ $self->{sessions} };
return;
}
sub register {
my ($kernel, $sender, $self) = @_[KERNEL, SENDER, OBJECT];
my $sender_id = $sender->ID();
$self->{sessions}->{$sender_id}++;
if ($self->{sessions}->{$sender_id} == 1) {
$kernel->refcount_increment($sender_id, __PACKAGE__);
$kernel->yield(__send_event => 'simplepoco_registered', $sender_id);
}
return;
}
sub unregister {
my ($kernel, $sender, $self) = @_[KERNEL, SENDER, OBJECT];
my $sender_id = $sender->ID();
my $record = delete $self->{sessions}->{$sender_id};
if ($record) {
$kernel->refcount_decrement($sender_id, __PACKAGE__);
$kernel->yield(__send_event => 'simplepoco_unregistered', $sender_id);
}
return;
}
sub __send_event {
my ($kernel, $self, $event, @args) = @_[KERNEL, OBJECT, ARG0..$#_];
return 1 if $self->_pluggable_process(EXAMPLE => $event, \(@args)) == PLUGIN_EAT_ALL;
$kernel->post($_, $event, @args) for keys %{ $self->{sessions} };
}
sub _send_ping {
my ($kernel, $self) = @_[KERNEL, OBJECT];
$kernel->yield(__send_event => 'simplepoco_ping', 'Wake up sleepy');
$kernel->delay(_send_ping => $self->{time} || 1);
return;
}
}
{
package SimplePoCo::Plugin;
use strict;
use warnings;
use POE::Component::Pluggable::Constants qw(:ALL);
sub new {
my $package = shift;
return bless { @_ }, $package;
}
sub plugin_register {
my ($self, $pluggable) = splice @_, 0, 2;
print "Plugin added\n";
$pluggable->plugin_register($self, 'EXAMPLE', 'all');
return 1;
}
sub plugin_unregister {
print "Plugin removed\n";
return 1;
}
sub EXAMPLE_ping {
my ($self, $pluggable) = splice @_, 0, 2;
my $text = ${ $_[0] };
print "Plugin got '$text'\n";
return PLUGIN_EAT_NONE;
}
}
use strict;
use warnings;
use POE;
my $pluggable = SimplePoCo->spawn(
alias => 'pluggable',
time => 1,
);
POE::Session->create(
package_states => [
main => [qw(_start simplepoco_registered simplepoco_ping)],
],
);
$poe_kernel->run();
sub _start {
my $kernel = $_[KERNEL];
$kernel->post(pluggable => 'register');
return;
}
sub simplepoco_registered {
print "Main program registered for events\n";
my $plugin = SimplePoCo::Plugin->new();
$pluggable->plugin_add('TestPlugin', $plugin);
return;
}
sub simplepoco_ping {
my ($heap, $text) = @_[HEAP, ARG0];
print "Main program got '$text'\n";
$heap->{got_ping}++;
$pluggable->shutdown() if $heap->{got_ping} == 3;
return;
}