Skip to content

Commit

Permalink
Convert POE::Resource::SIDs into a proper class.
Browse files Browse the repository at this point in the history
  • Loading branch information
rcaputo committed Apr 7, 2014
1 parent 32ff484 commit 68089ff
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 66 deletions.
18 changes: 10 additions & 8 deletions lib/POE/Kernel.pm
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ sub KR_ALIASES () { 3 } # \%kr_aliases,
sub KR_ACTIVE_SESSION () { 4 } # \$kr_active_session,
sub KR_QUEUE () { 5 } # \$kr_queue,
sub KR_ID () { 6 } # $unique_kernel_id,
sub KR_SESSION_IDS () { 7 } # \%kr_session_ids,
sub KR_SESSION_IDS () { 7 } # POE::Resource::SIDs object,
sub KR_SID_SEQ () { 8 } # \$kr_sid_seq,
sub KR_EXTRA_REFS () { 9 } # \$kr_extra_refs,
sub KR_SIZE () { 10 } # XXX UNUSED ???
Expand Down Expand Up @@ -588,7 +588,7 @@ sub _resolve_session {
return $session if defined $session;
# Resolve against IDs.
$session = $self->_data_sid_resolve($whatever);
$session = $self->[KR_SESSION_IDS]->resolve($whatever);
return $session if defined $session;
# Resolve against aliases.
Expand Down Expand Up @@ -823,7 +823,7 @@ sub new {
\$kr_active_session, # KR_ACTIVE_SESSION
$kr_queue, # KR_QUEUE - reference to an object
undef, # KR_ID
undef, # KR_SESSION_IDS - from POE::Resource::SIDS
undef, # KR_SESSION_IDS
undef, # KR_SID_SEQ - from POE::Resource::SIDS
undef, # KR_EXTRA_REFS
undef, # KR_SIZE
Expand All @@ -836,7 +836,9 @@ sub new {
POE::Resources->load();

$self->_recalc_id();
$self->_data_sid_set($self->[KR_ID], $self);

$self->[KR_SESSION_IDS] = POE::Resource::SIDs->new();
$self->[KR_SESSION_IDS]->set( $self->[KR_ID], $self );

# Initialize subsystems. The order is important.

Expand Down Expand Up @@ -1213,7 +1215,7 @@ sub _finalize_kernel {
$self->_data_sig_finalize();
$self->loop_finalize();
$self->_data_extref_finalize();
$self->_data_sid_finalize();
$self->[KR_SESSION_IDS]->finalize();
$self->_data_alias_finalize();
$self->_data_handle_finalize();
$self->_data_ev_finalize();
Expand Down Expand Up @@ -1461,7 +1463,7 @@ sub session_alloc {

# Allocate the session's data structure. This must be done before
# we dispatch anything regarding the new session.
my $new_sid = $self->_data_sid_allocate();
my $new_sid = $self->[KR_SESSION_IDS]->allocate();
$session->_set_id($new_sid);
$self->_data_ses_allocate($session, $new_sid, $kr_active_session->ID);

Expand Down Expand Up @@ -2467,7 +2469,7 @@ sub _recalc_id {
if (defined $old_id) {
$self->_data_sig_relocate_kernel_id($old_id, $new_id);
$self->_data_ses_relocate_kernel_id($old_id, $new_id);
$self->_data_sid_relocate_kernel_id($old_id, $new_id);
$self->[KR_SESSION_IDS]->reset_id($old_id, $new_id);
$self->_data_handle_relocate_kernel_id($old_id, $new_id);
$self->_data_ev_relocate_kernel_id($old_id, $new_id);
$self->_data_alias_relocate_kernel_id($old_id, $new_id);
Expand All @@ -2487,7 +2489,7 @@ sub ID_id_to_session {
_confess "<us> undefined ID in ID_id_to_session()" unless defined $id;
};

my $session = $self->_data_sid_resolve($id);
my $session = $self->[KR_SESSION_IDS]->resolve($id);
return $session if defined $session;

$self->_explain_return("ID does not exist");
Expand Down
101 changes: 59 additions & 42 deletions lib/POE/Resource/SIDs.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,97 +3,114 @@

package POE::Resource::SIDs;

use warnings;
use strict;


use vars qw($VERSION);
$VERSION = '1.358'; # NOTE - Should be #.### (three decimal places)

# These methods are folded into POE::Kernel;
package POE::Kernel;

use strict;
use constant {
MEMB_SESSIONS => 0,
MEMB_SEQUENCE => 1,

### Map session IDs to sessions. Map sessions to session IDs.
### Maintain a sequence number for determining the next session ID.
ASSERT_DATA => POE::Kernel::ASSERT_DATA(),
};

my %kr_session_ids;
# ( $session_id => $session_reference,
# ...,
# );

my $kr_sid_seq = 0;
sub new {
my ($class) = @_;

sub _data_sid_initialize {
$poe_kernel->[KR_SESSION_IDS] = \%kr_session_ids;
$poe_kernel->[KR_SID_SEQ] = \$kr_sid_seq;
return bless [
{ }, # MEMB_SESSIONS
0, # MEMB_SEQUENCE
], $class;
}

sub _data_sid_relocate_kernel_id {
my ($self, $old_id, $new_id) = @_;
$kr_session_ids{$new_id} = delete $kr_session_ids{$old_id}
if exists $kr_session_ids{$old_id};
}

### End-run leak checking.
sub finalize {
my ($self) = @_;

sub _data_sid_finalize {
my $finalized_ok = 1;
while (my ($sid, $ses) = each(%kr_session_ids)) {
_warn "!!! Leaked session ID: $sid = $ses\n";
while (my ($sid, $ses) = each(%{ $self->[MEMB_SESSIONS] })) {
POE::Kernel::_warn("!!! Leaked session ID: $sid = $ses\n");
$finalized_ok = 0;
}

return $finalized_ok;
}

### Allocate a new session ID.

sub _data_sid_allocate {
my $self = shift;
1 while exists $kr_session_ids{++$kr_sid_seq};
return $kr_sid_seq;
sub allocate {
my ($self) = @_;

my $seq = $self->[MEMB_SEQUENCE];
1 while exists $self->[MEMB_SESSIONS]{++$seq};
$self->[MEMB_SEQUENCE] = $seq;

return $seq;
}

### Set a session ID.

sub _data_sid_set {
sub set {
my ($self, $sid, $session) = @_;
$kr_session_ids{$sid} = $session;
$self->[MEMB_SESSIONS]{$sid} = $session;
}

### Clear a session ID.

sub _data_sid_clear {
sub clear {
my ($self, $sid) = @_;

return delete $kr_session_ids{$sid} unless ASSERT_DATA;
return delete $self->[MEMB_SESSIONS]{$sid} unless ASSERT_DATA;

my $removed = delete $kr_session_ids{$sid};
_trap("unknown SID '$sid'") unless defined $removed;
my $removed = delete $self->[MEMB_SESSIONS]{$sid};
POE::Kernel::_trap("unknown SID '$sid'") unless defined $removed;
$removed;
}

### Resolve a session ID into its session.

sub _data_sid_resolve {
sub resolve {
my ($self, $sid) = @_;
return $kr_session_ids{$sid};
return(
exists($self->[MEMB_SESSIONS]{$sid})
? $self->[MEMB_SESSIONS]{$sid}
: undef
);
}


sub reset_id {
my ($self, $old_id, $new_id) = @_;

if (ASSERT_DATA) {
POE::Kernel::_trap("unknown old SID '$old_id'") unless (
exists $self->[MEMB_SESSIONS]{$old_id}
);
POE::Kernel::_trap("new SID '$new_id' already taken'") if (
exists $self->[MEMB_SESSIONS]{$new_id}
);
}

$self->[MEMB_SESSIONS]{$new_id} = delete $self->[MEMB_SESSIONS]{$old_id};
}


1;

__END__
=head1 NAME
POE::Resource::SIDs - internal session ID manager for POE::Kernel
POE::Resource::SIDs - Helper class to manage session IDs for POE::Kernel
=head1 SYNOPSIS
There is no public API.
=head1 DESCRIPTION
POE::Resource::SIDs is a mix-in class for POE::Kernel. It provides
the features necessary to manage session IDs. It is used internally
by POE::Kernel, so it has no public interface.
POE uses POE::Resource::SIDs internally to manage session IDs.
=head1 SEE ALSO
Expand Down
4 changes: 2 additions & 2 deletions lib/POE/Resource/Sessions.pm
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ sub _data_ses_allocate {
];

# For the ID to session reference lookup.
$self->_data_sid_set($sid, $session);
$self->[KR_SESSION_IDS]->set($sid, $session);

# For the stringy to blessed session reference lookup.
$kr_session_refs{$session} = $session;
Expand Down Expand Up @@ -217,7 +217,7 @@ sub _data_ses_free {

# Things which do not hold reference counts.

$self->_data_sid_clear($sid); # Remove from SID tables.
$self->[KR_SESSION_IDS]->clear($sid); # Remove from SID tables.
$self->_data_sig_clear_session($sid); # Remove all leftover signals.

# Things which do hold reference counts.
Expand Down
14 changes: 9 additions & 5 deletions t/20_resources/00_base/sessions.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ is($poe_kernel->_data_ses_count(), 1, "only POE::Kernel exists");

# Allocate a dummy session for testing.

my $kr_sids = $poe_kernel->[POE::Kernel::KR_SESSION_IDS];

my $child = bless [ ], "POE::Session";
my $child_sid = $poe_kernel->_data_sid_allocate();
my $child_sid = $kr_sids->allocate();
$child->_set_id($child_sid);

$poe_kernel->_data_ses_allocate(
Expand Down Expand Up @@ -57,7 +59,7 @@ is(
# Ensure that the session's ID was set.

is(
$poe_kernel->_data_sid_resolve($child_sid), $child,
$kr_sids->resolve($child_sid), $child,
"child session's ID is correct"
);

Expand Down Expand Up @@ -118,8 +120,10 @@ ok(
# Create a grandchild session (child of child). Verify that its place
# in the grand scheme of things is secure.

my $kr_sids = $poe_kernel->[POE::Kernel::KR_SESSION_IDS];

my $grand = bless [ ], "POE::Session";
my $grand_id = $poe_kernel->_data_sid_allocate();
my $grand_id = $kr_sids->allocate();
$grand->_set_id($grand_id);

$poe_kernel->_data_ses_allocate(
Expand Down Expand Up @@ -168,7 +172,7 @@ my $base_grand_refcount = $poe_kernel->_data_ses_refcount($grand_id);
# that its place in the grand scheme of things is secure.

my $great = bless [ ], "POE::Session";
my $great_id = $poe_kernel->_data_sid_allocate();
my $great_id = $kr_sids->allocate();
$great->_set_id($great_id);

$poe_kernel->_data_ses_allocate(
Expand Down Expand Up @@ -360,7 +364,7 @@ ok(
# Attempt to allocate a session for a nonexistent parent.

my $bogus = bless [ ], "POE::Session";
my $bogus_sid = $poe_kernel->_data_sid_allocate();
my $bogus_sid = $kr_sids->allocate();
$bogus->_set_id($bogus_sid);

eval {
Expand Down
16 changes: 9 additions & 7 deletions t/20_resources/00_base/sids.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,30 @@ BEGIN { use_ok("POE") }
# Allocate a session ID. It starts at 2 because POE::Kernel's virtual
# session has already been allocated.

my $sid = $poe_kernel->_data_sid_allocate();
my $kr_sids = $poe_kernel->[POE::Kernel::KR_SESSION_IDS()];

my $sid = $kr_sids->allocate();
ok($sid == 1, "first user SID is expected (got $sid)");

# Set an ID for a session.

$poe_kernel->_data_sid_set($sid, "session");
$kr_sids->set($sid, "session");

# Ensure that the session ID resolves.

my $resolved_session = $poe_kernel->_data_sid_resolve($sid);
my $resolved_session = $kr_sids->resolve($sid);
ok($resolved_session eq "session", "session ID resolves correctly");

# Remove the ID from the session. This relies on a side effect of the
# remove function that returns the removed value. That may change in
# the future.

my $removed = $poe_kernel->_data_sid_clear($sid);
my $removed = $kr_sids->clear($sid);
ok($removed eq "session", "session ID $sid removes $removed correctly");

# What happens if a session doesn't exist?

eval { $poe_kernel->_data_sid_clear("session") };
eval { $kr_sids->clear("session") };
ok(
$@ && $@ =~ /unknown SID/,
"can't clear a sid for a nonexistent session"
Expand All @@ -46,11 +48,11 @@ ok(
# POE::Kernel itself has allocated a SID. Remove that. This also
# relies on undocumented side effects that can change at any time.

$removed = $poe_kernel->_data_sid_clear($poe_kernel->ID);
$removed = $kr_sids->clear($poe_kernel->ID());
ok($removed eq $poe_kernel, "successfully removed POE::Kernel's SID");

# Finalize the subsystem and ensure it shut down cleanly.

ok($poe_kernel->_data_sid_finalize(), "POE::Resource::SIDs finalized ok");
ok($kr_sids->finalize(), "POE::Resource::SIDs finalized ok");

1;
4 changes: 2 additions & 2 deletions t/20_resources/00_base/signals.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ $poe_kernel->_data_sig_initialize();

sub create_session {
my $session = bless [ ], "POE::Session";
my $sid = $poe_kernel->_data_sid_allocate();
my $sid = $poe_kernel->[POE::Kernel::KR_SESSION_IDS]->allocate();

$session->_set_id($sid);
$poe_kernel->_data_ses_allocate(
Expand Down Expand Up @@ -319,7 +319,7 @@ ok(
# Nonmaskable signals terminate sessions no matter what.

{ my $ses = bless [ ], "POE::Session";
my $sid = $poe_kernel->_data_sid_allocate();
my $sid = $poe_kernel->[POE::Kernel::KR_SESSION_IDS]->allocate();

$ses->_set_id($sid);
$poe_kernel->_data_ses_allocate(
Expand Down

0 comments on commit 68089ff

Please sign in to comment.