This is a second patch, this has around 0.5% overhead when no hooks are registred.
attached is also a program called poeprofiler.pl just require it and it will show a
profiler analysis after your program is finished
--- oldpoe/poe/POE/Kernel.pm Wed Jun 13 17:46:19 2001
+++ poe/POE/Kernel.pm Sun Jul 8 22:11:33 2001
@@ -9,6 +9,14 @@
use vars qw( $poe_kernel $poe_main_window );
+use vars qw($hook_session $hook_source_session $hook_local_state $hook_etc $hook_file
+$hook_line $hook_dispatch $hook_return);
+use vars qw(%pre_dispatch_hooks %post_dispatch_hooks %pre_hooks %post_hooks $hook_id
+$hooks @hooks);
+
+($hook_id, $hooks) = (1,0);
+$pre_dispatch_hooks{""} = {};
+$post_dispatch_hooks{""} = {};
+
+
#------------------------------------------------------------------------------
sub import {
@@ -794,6 +802,9 @@
0, # SS_ALCOUNT
];
+ $pre_dispatch_hooks{$session} = {};
+ $post_dispatch_hooks{$session} = {};
+
# For the ID to session reference lookup.
$kr_session_ids{$kr_id_index} = $session;
@@ -918,9 +929,41 @@
my $hold_active_session = $kr_active_session;
$kr_active_session = $session;
+
+
+
# Dispatch the event, at long last.
- my $return =
- $session->_invoke_state($source_session, $local_state, $etc, $file, $line);
+
+ my $return;
+
+
+ if($hooks) {
+
+ ($hook_session, $hook_source_session,$hook_local_state, $hook_etc, $hook_file,
+$hook_line, $hook_dispatch) =
+ ( $session, $source_session, $local_state, $etc, $file,
+ $line, 0);
+
+
+ for(values %{$pre_dispatch_hooks{""}->{""}}, values
+%{$pre_dispatch_hooks{""}->{$local_state}},
+ values %{$pre_dispatch_hooks{"$session"}->{""}}, values
+%{$pre_dispatch_hooks{"$session"}->{$local_state}}) {
+ $hook_dispatch = 1 if($hook_return = $_->());
+ }
+
+ unless($hook_dispatch) {
+ $hook_return = $return = $session->_invoke_state($source_session, $local_state,
+$etc, $file, $line);
+ }
+
+ for(values %{$post_dispatch_hooks{""}->{""}}, values
+%{$post_dispatch_hooks{""}->{$local_state}},
+ values %{$post_dispatch_hooks{"$session"}->{""}}, values
+%{$post_dispatch_hooks{"$session"}->{$local_state}}) {
+ $hook_dispatch = 1 if($hook_return = $_->());
+ }
+
+
+ ($hook_session, $hook_source_session, $hook_local_state, $hook_etc, $hook_file,
+$hook_line, $hook_return, $hook_dispatch) =
+ (undef, undef, undef, undef, undef, undef, undef, undef);
+
+ } else {
+ $return = $session->_invoke_state($source_session, $local_state, $etc, $file,
+$line);
+ }
# Stringify the state's return value if it belongs in the POE
# namespace. $return's scope exists beyond the post-dispatch
@@ -1002,6 +1045,10 @@
delete $kr_sessions{$session}->[SS_CHILDREN]->{$_};
{% ses_refcount_dec $session %}
+
+ delete($pre_dispatch_hooks{$session});
+ delete($post_dispatch_hooks{$session});
+
}
# Free any signals that the departing session allocated.
@@ -2890,6 +2937,80 @@
return ESRCH;
}
+#==============================================================================
+# HOOKS
+#==============================================================================
+
+my %hooks = ( dispatch_state => 1);
+
+sub hook_set {
+ my ($self, $when, $session, $hook, $callback, $event) = @_;
+
+ if($session) {
+ croak("Session $session is not a registred session")
+unless(exists($self->[KR_SESSIONS]->{"$session"}));
+ }
+ croak("Hook $hook is not an avaible hook") unless(exists($hooks{$hook}));
+ if($when) {
+ croak("You cannot register a hook to run '$when', only 'pre' and 'post'") if($when
+ne 'post' && $when ne 'pre');
+ } else {
+ $when = 'pre';
+ }
+ carp("We need a callback") unless(ref($callback));
+
+ if($hook eq 'dispatch_state') {
+
+ if($when eq 'pre') {
+ $pre_dispatch_hooks{"$session"}->{$event}->{$callback} = $callback;
+ } else {
+ $post_dispatch_hooks{"$session"}->{$event}->{$callback} = $callback;
+ }
+ $hooks[$hook_id] = [$session,$when,$callback,$event];
+ } else {
+ if($when eq 'pre') {
+ $pre_hooks{"$session"}->{$callback} = $callback;
+ } else {
+ $post_hooks{"$session"}->{$callback} = $callback;
+ }
+ $hooks[$hook_id] = [$session,$when,$callback];
+ }
+
+
+
+ $hooks++;
+ return $hook_id++;
+}
+
+sub hook_remove {
+ my($self, $id) = @_;
+
+ my $hook = delete($hooks[$id]);
+ carp("No hook with id '$id' exists") unless(ref($hook) eq 'ARRAY');
+
+ if(@$hook == 3) {
+ if($hook->[1] eq 'pre') {
+ delete($pre_hooks{$hook->[0]}->{$hook->[2]});
+ delete($pre_hooks{$hook->[0]}) unless(@{$pre_hooks{$hook->[0]}});
+ } else {
+ delete($post_hooks{$hook->[0]}->{$hook->[2]});
+ delete($post_hooks{$hook->[0]}) unless(@{$post_hooks{$hook->[0]}});
+ }
+ } else {
+ if($hook->[1] eq 'pre') {
+ delete($pre_dispatch_hooks{$hook->[0]}->{$hook->[3]}->{$hook->[2]});
+ delete($pre_dispatch_hooks{$hook->[0]}->{$hook->[3]})
+unless(@{$pre_dispatch_hooks{$hook->[0]}->{$hook->[3]}});
+ delete($pre_dispatch_hooks{$hook->[0]})
+unless(@{$pre_dispatch_hooks{$hook->[0]}});
+ } else {
+ delete($post_dispatch_hooks{$hook->[0]}->{$hook->[3]}->{$hook->[2]});
+ delete($post_dispatch_hooks{$hook->[0]}->{$hook->[3]})
+unless(@{$post_dispatch_hooks{$hook->[0]}->{$hook->[3]}});
+ delete($post_dispatch_hooks{$hook->[0]})
+unless(@{$post_dispatch_hooks{$hook->[0]}});
+ }
+
+ }
+ $hooks--;
+}
+
+
+
###############################################################################
# Bootstrap the kernel. This is inherited from a time when multiple
# kernels could be present in the same Perl process.
@@ -2897,6 +3018,7 @@
POE::Kernel->new();
###############################################################################
+
1;
__END__
@@ -3080,6 +3202,12 @@
# kernel if called outside any session.
$session = $kernel->get_active_session();
+Kernel hooks:
+
+ # Kernel hooks lets you set hooks at varius points in the kernel
+ $hookid = $kernel->hook_set($when, $session, $hook, $callback, $event);
+ $kernel->hook_remeve($hookid);
+
Exported symbols:
# A reference to the global POE::Kernel instance.
@@ -4096,6 +4224,99 @@
tediously need to include C<SESSION> with every call.
=back
+
+=head2 Kernel Hooks
+
+Kernel Hooks provide a way to add in hooks at various points in the
+kernels exeuction. The following two functions control thiss behaviour
+
+=over 2
+
+=item my $hook_id = $poe_kernel->hook_set($when, $session $hook, $callback, $event);
+
+This sets a hook.
+
+=over 2
+
+=item $when
+
+Should be pre or post depending on when you want the hook executed
+
+=item $session
+
+The session you want to watch, empty for all sessions
+
+=item $hook
+
+What kind of hook, (hooks listed below)
+
+=item $callback
+
+A CODEREF to a subroutine
+
+=item $event
+
+The name of the state being called, only usefull for dispatch_state hook
+
+=back
+
+=item my $poe_kernel->hook_remove($hook_id);
+
+This removes the hook with the corresonding id
+
+=item Hooks
+
+=over 2
+
+=item dispatch_state
+
+This hook is called just before and just after dispatch_state,
+if a pre hook returns true, it is assumed it has taken care of the
+dispatch and POEs normal dispatch is ignored! If you do not want this,
+make sure all dispatches end with return 0;
+
+dispatch_state exposes quite a lot of variables, they are not exported and
+should be referenced as $POE::Kernel::variable
+
+=over 2
+
+=item $hook_session
+
+This is the session being invoked
+
+=item $hook_source_session
+
+This is the source of the event
+
+=item $hook_local_state
+
+This is the state being invoked
+
+=item $hook_etc
+
+This is an arrayref of arguments
+
+=item $hook_file
+
+What file made the event
+
+=item $hook_line
+
+And corresponding line!
+
+=item $hook_dispatch
+
+This is true if a hook has already dispatched the event
+
+=item $hook_return
+
+The return value from the dispatch
+
+=back
+
+=back
+
+
=head1 Using POE with Other Event Loops
--- oldpoe/poe/POE/Kernel.pm Wed Jun 13 17:46:19 2001
+++ poe/POE/Kernel.pm Sun Jul 8 22:11:33 2001
@@ -9,6 +9,14 @@
use vars qw( $poe_kernel $poe_main_window );
+use vars qw($hook_session $hook_source_session $hook_local_state $hook_etc $hook_file
+$hook_line $hook_dispatch $hook_return);
+use vars qw(%pre_dispatch_hooks %post_dispatch_hooks %pre_hooks %post_hooks $hook_id
+$hooks @hooks);
+
+($hook_id, $hooks) = (1,0);
+$pre_dispatch_hooks{""} = {};
+$post_dispatch_hooks{""} = {};
+
+
#------------------------------------------------------------------------------
sub import {
@@ -794,6 +802,9 @@
0, # SS_ALCOUNT
];
+ $pre_dispatch_hooks{$session} = {};
+ $post_dispatch_hooks{$session} = {};
+
# For the ID to session reference lookup.
$kr_session_ids{$kr_id_index} = $session;
@@ -918,9 +929,41 @@
my $hold_active_session = $kr_active_session;
$kr_active_session = $session;
+
+
+
# Dispatch the event, at long last.
- my $return =
- $session->_invoke_state($source_session, $local_state, $etc, $file, $line);
+
+ my $return;
+
+
+ if($hooks) {
+
+ ($hook_session, $hook_source_session,$hook_local_state, $hook_etc, $hook_file,
+$hook_line, $hook_dispatch) =
+ ( $session, $source_session, $local_state, $etc,
+$file, $line, 0);
+
+
+ for(values %{$pre_dispatch_hooks{""}->{""}}, values
+%{$pre_dispatch_hooks{""}->{$local_state}},
+ values %{$pre_dispatch_hooks{"$session"}->{""}}, values
+%{$pre_dispatch_hooks{"$session"}->{$local_state}}) {
+ $hook_dispatch = 1 if($hook_return = $_->());
+ }
+
+ unless($hook_dispatch) {
+ $hook_return = $return = $session->_invoke_state($source_session,
+$local_state, $etc, $file, $line);
+ }
+
+ for(values %{$post_dispatch_hooks{""}->{""}}, values
+%{$post_dispatch_hooks{""}->{$local_state}},
+ values %{$post_dispatch_hooks{"$session"}->{""}}, values
+%{$post_dispatch_hooks{"$session"}->{$local_state}}) {
+ $hook_dispatch = 1 if($hook_return = $_->());
+ }
+
+
+ ($hook_session, $hook_source_session, $hook_local_state, $hook_etc, $hook_file,
+$hook_line, $hook_return, $hook_dispatch) =
+ (undef, undef, undef, undef, undef, undef, undef, undef);
+
+ } else {
+ $return = $session->_invoke_state($source_session, $local_state, $etc, $file,
+$line);
+ }
# Stringify the state's return value if it belongs in the POE
# namespace. $return's scope exists beyond the post-dispatch
@@ -1002,6 +1045,10 @@
delete $kr_sessions{$session}->[SS_CHILDREN]->{$_};
{% ses_refcount_dec $session %}
+
+ delete($pre_dispatch_hooks{$session});
+ delete($post_dispatch_hooks{$session});
+
}
# Free any signals that the departing session allocated.
@@ -2890,6 +2937,80 @@
return ESRCH;
}
+#==============================================================================
+# HOOKS
+#==============================================================================
+
+my %hooks = ( dispatch_state => 1);
+
+sub hook_set {
+ my ($self, $when, $session, $hook, $callback, $event) = @_;
+
+ if($session) {
+ croak("Session $session is not a registred session")
+unless(exists($self->[KR_SESSIONS]->{"$session"}));
+ }
+ croak("Hook $hook is not an avaible hook") unless(exists($hooks{$hook}));
+ if($when) {
+ croak("You cannot register a hook to run '$when', only 'pre' and 'post'")
+if($when ne 'post' && $when ne 'pre');
+ } else {
+ $when = 'pre';
+ }
+ carp("We need a callback") unless(ref($callback));
+
+ if($hook eq 'dispatch_state') {
+
+ if($when eq 'pre') {
+ $pre_dispatch_hooks{"$session"}->{$event}->{$callback} = $callback;
+ } else {
+ $post_dispatch_hooks{"$session"}->{$event}->{$callback} = $callback;
+ }
+ $hooks[$hook_id] = [$session,$when,$callback,$event];
+ } else {
+ if($when eq 'pre') {
+ $pre_hooks{"$session"}->{$callback} = $callback;
+ } else {
+ $post_hooks{"$session"}->{$callback} = $callback;
+ }
+ $hooks[$hook_id] = [$session,$when,$callback];
+ }
+
+
+
+ $hooks++;
+ return $hook_id++;
+}
+
+sub hook_remove {
+ my($self, $id) = @_;
+
+ my $hook = delete($hooks[$id]);
+ carp("No hook with id '$id' exists") unless(ref($hook) eq 'ARRAY');
+
+ if(@$hook == 3) {
+ if($hook->[1] eq 'pre') {
+ delete($pre_hooks{$hook->[0]}->{$hook->[2]});
+ delete($pre_hooks{$hook->[0]}) unless(@{$pre_hooks{$hook->[0]}});
+ } else {
+ delete($post_hooks{$hook->[0]}->{$hook->[2]});
+ delete($post_hooks{$hook->[0]}) unless(@{$post_hooks{$hook->[0]}});
+ }
+ } else {
+ if($hook->[1] eq 'pre') {
+ delete($pre_dispatch_hooks{$hook->[0]}->{$hook->[3]}->{$hook->[2]});
+ delete($pre_dispatch_hooks{$hook->[0]}->{$hook->[3]})
+unless(@{$pre_dispatch_hooks{$hook->[0]}->{$hook->[3]}});
+ delete($pre_dispatch_hooks{$hook->[0]})
+unless(@{$pre_dispatch_hooks{$hook->[0]}});
+ } else {
+ delete($post_dispatch_hooks{$hook->[0]}->{$hook->[3]}->{$hook->[2]});
+ delete($post_dispatch_hooks{$hook->[0]}->{$hook->[3]})
+unless(@{$post_dispatch_hooks{$hook->[0]}->{$hook->[3]}});
+ delete($post_dispatch_hooks{$hook->[0]})
+unless(@{$post_dispatch_hooks{$hook->[0]}});
+ }
+
+ }
+ $hooks--;
+}
+
+
+
###############################################################################
# Bootstrap the kernel. This is inherited from a time when multiple
# kernels could be present in the same Perl process.
@@ -2897,6 +3018,7 @@
POE::Kernel->new();
###############################################################################
+
1;
__END__
@@ -3080,6 +3202,12 @@
# kernel if called outside any session.
$session = $kernel->get_active_session();
+Kernel hooks:
+
+ # Kernel hooks lets you set hooks at varius points in the kernel
+ $hookid = $kernel->hook_set($when, $session, $hook, $callback, $event);
+ $kernel->hook_remeve($hookid);
+
Exported symbols:
# A reference to the global POE::Kernel instance.
@@ -4096,6 +4224,99 @@
tediously need to include C<SESSION> with every call.
=back
+
+=head2 Kernel Hooks
+
+Kernel Hooks provide a way to add in hooks at various points in the
+kernels exeuction. The following two functions control thiss behaviour
+
+=over 2
+
+=item my $hook_id = $poe_kernel->hook_set($when, $session $hook, $callback, $event);
+
+This sets a hook.
+
+=over 2
+
+=item $when
+
+Should be pre or post depending on when you want the hook executed
+
+=item $session
+
+The session you want to watch, empty for all sessions
+
+=item $hook
+
+What kind of hook, (hooks listed below)
+
+=item $callback
+
+A CODEREF to a subroutine
+
+=item $event
+
+The name of the state being called, only usefull for dispatch_state hook
+
+=back
+
+=item my $poe_kernel->hook_remove($hook_id);
+
+This removes the hook with the corresonding id
+
+=item Hooks
+
+=over 2
+
+=item dispatch_state
+
+This hook is called just before and just after dispatch_state,
+if a pre hook returns true, it is assumed it has taken care of the
+dispatch and POEs normal dispatch is ignored! If you do not want this,
+make sure all dispatches end with return 0;
+
+dispatch_state exposes quite a lot of variables, they are not exported and
+should be referenced as $POE::Kernel::variable
+
+=over 2
+
+=item $hook_session
+
+This is the session being invoked
+
+=item $hook_source_session
+
+This is the source of the event
+
+=item $hook_local_state
+
+This is the state being invoked
+
+=item $hook_etc
+
+This is an arrayref of arguments
+
+=item $hook_file
+
+What file made the event
+
+=item $hook_line
+
+And corresponding line!
+
+=item $hook_dispatch
+
+This is true if a hook has already dispatched the event
+
+=item $hook_return
+
+The return value from the dispatch
+
+=back
+
+=back
+
+
=head1 Using POE with Other Event Loops
poeprofiler.pl