<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Declare the package
package POE::Component::WxPoeIO;
use strict;
use warnings;

# Initialize our version
our $VERSION = '0.001001';

# Import what we need from the POE namespace
use POE;

# Other miscellaneous modules
use Carp;

# Set some constants
BEGIN {
	# Debug fun!
	if ( ! defined &amp;DEBUG ) {
		eval "sub DEBUG () { 0 }";
	}
}

# Setup IO process
sub new {
	# Get the OOP's type
	my $type = shift;

	# Sanity checking
	if ( @_ &amp; 1 ) {
		croak( 'POE::Component::WxPoeIO-&gt;new needs even number of options' );
	}

	# The options hash
	my %opt = @_;

	# Our own options
	my ( $ALIAS, $SIGNAL_KEYS, $QUEUE );

	# Get the session alias
	if ( exists $opt{ALIAS} ) {
		$ALIAS = $opt{ALIAS};
		delete $opt{ALIAS};
	} else {
		# Debugging info...
		if ( DEBUG ) {
			warn 'Using default ALIAS = WxPoeIO';
		}

		# Set the default
		$ALIAS = 'WxPoeIO';
	}
	if ( exists $opt{SIGNAL_QUEUE} ) {
		$QUEUE = $opt{SIGNAL_QUEUE};
		delete $opt{SIGNAL_QUEUE};
	} else {
		# Debugging info...
		if ( DEBUG ) {
			warn 'No signal queue imported. Generating an array pointer.\n\tExport using EXPORT_SIG_QUEUE_PTR';
		}
		# Set an empty array pointer
		$QUEUE = [];
	}
	
	# Get the signal keys defined by root script
	# These are held constant between Poe session and Wx frames
	if ( exists $opt{'SIGNAL_KEYS'} ) {
		$SIGNAL_KEYS = $opt{'SIGNAL_KEYS'};
		delete $opt{'SIGNAL_KEYS'};

		# Check if it is defined
		if ( !$SIGNAL_KEYS or $SIGNAL_KEYS!~/HASH/i ) {
			# reset $SIGNAL_KEYS to be only undef
			$SIGNAL_KEYS = undef;
		}
	} else {
		# Set signals to undefined because no key constants have been sent
		$SIGNAL_KEYS = undef;
	}

	# Anything left over is unrecognized
	if ( DEBUG ) {
		if ( keys %opt &gt; 0 ) {
			croak 'Unrecognized options were present in POE::Component::WxPoeIO-&gt;new -&gt; ' . join( ', ', keys %opt );
		}
	}

	# Create a new session for ourself
	POE::Session-&gt;create(
		# Our subroutines
		'inline_states'	=&gt;	{
			# Maintenance events
			'_start'	=&gt;	\&amp;StartIO,
			'_stop'		=&gt;	sub {},

			# Config a signal [key] push for use...this is not the same as registing for a signal broadcast
			'CONFIG_SIGNAL'	=&gt;	\&amp;Config_signal,

			# Register an IO session
			'REGISTER_SESSION'	=&gt;	\&amp;Register_session,

			# Unregister an IO session
			'UNREGISTER_SESSION'	=&gt;	\&amp;UnRegister_session,

			# Register an IO frame
			'REGISTER_FRAME'	=&gt;	\&amp;Register_frame,

			# Unregister an IO frame
			'UNREGISTER_FRAME'	=&gt;	\&amp;UnRegister_frame,

			# Register a wxframe to wxframe IO on FRAME_TO_FRAME channel
			'REGISTER_FRAME_TO_FRAME'	=&gt;	\&amp;Register_frame_to_frame,

			# Trigger signals
			'TRIGGER_SIGNALS'		=&gt;	\&amp;trigger_signals,

			# Terminate signal and clean up state
			'END_SIGNAL'		=&gt;	\&amp;end_signal,

			# SIGNAL SOMETHING to POE!
			'TO_POE'		=&gt;	\&amp;toPoe,
			# SIGNAL SOMETHING to WxFrame!
			'TO_WX'			=&gt;	\&amp;toWx,

			# Manage POE SIGNAL
			'_MANAGE_LATCHING'	=&gt;	\&amp;_manage_latching,

			# Manage POE SIGNAL
			'_MANAGE_TO_POE'	=&gt;	\&amp;_manage_to_poe,

			# Wait loop for latched POE SIGNAL
			'_WAIT_ON_LATCH'	=&gt;	\&amp;_wait_on_latch,

			# Wait loop for locked POE SIGNAL
			'_WAIT_TO_POE'	=&gt;	\&amp;_wait_to_poe,

			# export method to obtain the pointer to the signal queue
			'EXPORT_SIG_QUEUE_PTR' =&gt; \&amp;export_queue_ptr,
			
			# We are done!
			'SHUTDOWN'	=&gt;	\&amp;StopIO,
		},

		# Set up the heap for ourself
		'heap'		=&gt;	{
			'ALIAS'		=&gt;	$ALIAS,

			# The session registation table
			'WXPOEIO'	=&gt;	{},

			# SIGNAL_KEYS
			'SIGNAL_KEYS'	=&gt;	$SIGNAL_KEYS,

			# The frame registration table
			'WXFRAMEIO'	=&gt;	{},

			# The channel registration table
			'WXPOEIO_CHANNELS'	=&gt;	{'MAIN'=&gt;undef},

			# The channel registration table
			'WXPOEIO_QUEUE'	=&gt;	$QUEUE,
		},
	) or die 'Unable to create a new session!';

	# Return success
	return 1;
}

# Configure a new io signal for latching and locking
sub Config_signal {
	# Get the arguments
	my $args = $_[ ARG0 ];

	my %loc_args = ('SIGNAL_CHANNEL'=&gt;'MAIN','LATCH'=&gt;1,'TIMEOUT'=&gt;0,'LOCK'=&gt;0,'RETRIES'=&gt;100);

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}

	if ( ! defined $args-&gt;{SIGNAL_CHANNEL} ) {
		if ( DEBUG ) {
			warn "Did not get a signal channel for signal: ".$args-&gt;{SIGNAL_KEY}." - using default [MAIN] channel";
		}
	}
	if ( exists $args-&gt;{SIGNAL_CHANNEL} and $args-&gt;{SIGNAL_CHANNEL} ) {
		$loc_args{SIGNAL_CHANNEL} = $args-&gt;{SIGNAL_CHANNEL};
	}
	if ( exists $args-&gt;{LATCH} and !$args-&gt;{LATCH} ) {
		$loc_args{LATCH} = 0;
	}
	if ( exists $args-&gt;{TIMEOUT} and $args-&gt;{TIMEOUT} ) {
		$loc_args{TIMEOUT} = $args-&gt;{TIMEOUT};
	}
	if ( exists $args-&gt;{LOCK} and $args-&gt;{LOCK} ) {
		$loc_args{LOCK} = 1;
	}
	if ( exists $args-&gt;{RETRIES} ) {
		$loc_args{RETRIES} = $args-&gt;{RETRIES};
		# Force falsy state to be an integer 0
		if(!$loc_args{RETRIES}) {
			$loc_args{RETRIES} = 0;
		}
	}

	if ( !exists $_[HEAP]-&gt;{SIGNAL_KEYS}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
		warn 'Setting undefined SIGNAL KEY ['.$args-&gt;{SIGNAL_KEY}.']. Possible void context.';
		if ( DEBUG ) {
			warn 'Signal key ['.$args-&gt;{SIGNAL_KEY}.'] not properly initialized';
		}
	}
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WXPOEIO_CHANNEL} = $loc_args{SIGNAL_CHANNEL};
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{LATCH} = $loc_args{LATCH};
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{LOCK} = $loc_args{LOCK};
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{TIMEOUT} = $loc_args{TIMEOUT};
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{RETRIES} = $loc_args{RETRIES};
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{IS_LATCHED} = 0;
	if ( !exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} }  or !$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} } ) {
		$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} } = {};
	}
	$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} }-&gt;{IS_LOCKED} = 0;
	$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} }-&gt;{IS_NOISY} = 0;
	$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{ $loc_args{SIGNAL_CHANNEL} }-&gt;{NOISE} = undef;

	# Config complete!
	return 1;
}

# Register a session to watch/wait for io signal
sub Register_session {
	# Get the arguments
	my $args = $_[ ARG0 ];

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}

	if ( ! defined $args-&gt;{SESSION} ) {
		if ( DEBUG ) {
			warn "Did not get a TargetSession for SignalKey: ".$args-&gt;{SIGNAL_KEY};
		}
		return undef;
	} else {
		# Convert actual POE::Session objects to their ID
		if ( UNIVERSAL::isa( $args-&gt;{SESSION}, 'POE::Session') ) {
			$args-&gt;{SESSION} = $args-&gt;{SESSION}-&gt;ID;
		}
	}
	if ( ! defined $args-&gt;{EVT_METHOD} ) {
		if ( DEBUG ) {
			warn "Did not get an EvtMethod for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and Target Session: ".$args-&gt;{SESSION};
		}
		return undef;
	}

#	# register within the WXPOEIO hash structure
	if ( ! exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
		$_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} } = {};
	}

	if ( ! exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} } ) {
			$_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} } = {};
	}

	# Finally store the event method in the signal key hash
	if ( exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} }-&gt;{ $args-&gt;{EVT_METHOD} } ) {
		# Duplicate record...
		if ( DEBUG ) {
			warn "Tried to register a duplicate! -&gt; LogName: ".$args-&gt;{SIGNAL_KEY}." -&gt; Target Session: ".$args-&gt;{SESSION}." -&gt; Event: ".$args-&gt;{EVT_METHOD};
		}
	} else {
		$_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} }-&gt;{ $args-&gt;{EVT_METHOD} } = 1;
	}

	# All registered!
	return 1;
}

# Delete a watcher session
sub UnRegister_session {
	# Get the arguments
	my $args = $_[ ARG0 ];

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}
	if ( ! defined $args-&gt;{SESSION} ) {
		if ( DEBUG ) {
			warn "Did not get a TargetSession for SignalKey: ".$args-&gt;{SIGNAL_KEY};
		}
		return undef;
	} else {
		# Convert actual POE::Session objects to their ID
		if ( UNIVERSAL::isa( $args-&gt;{SESSION}, 'POE::Session') ) {
			$args-&gt;{SESSION} = $args-&gt;{SESSION}-&gt;ID;
		}
	}

	if ( ! defined $args-&gt;{EVT_METHOD} ) {
		if ( DEBUG ) {
			warn "Did not get an EvtMethod for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and Target Session: ".$args-&gt;{SESSION};
		}
		return undef;
	}

	# Search through the registrations for this specific one
	if ( exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
		# Scan it for targetsession
		if ( exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} } ) {
			# Scan for the proper event!
			foreach my $evt_meth ( keys %{ $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} } } ) {
				if ( $evt_meth eq $args-&gt;{EVT_METHOD} ) {
					# Found a match, delete it!
					delete $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} }-&gt;{ $evt_meth };
					if ( scalar keys %{ $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} } } == 0 ) {
						delete $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{ $args-&gt;{SESSION} };
					}

					# Return success
					return 1;
				}
			}
		}
	}

	# Found nothing...
	return undef;
}

# Register a wxframe to watch/wait for io signal
sub Register_frame {
	# Get the arguments
	my $args = $_[ ARG0 ];

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}
	my $frame = 'DEFAULT';
	if ( exists $args-&gt;{WXFRAME_IDENT} ) {
		$frame = $args-&gt;{WXFRAME_IDENT};
	}
	if ( ! defined $frame ) {
		if ( DEBUG ) {
			warn "Did not get a valid frame name for SignalKey: ".$args-&gt;{SIGNAL_KEY}," and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}
	if ( ! defined $args-&gt;{WX_METHOD} ) {
		if ( DEBUG ) {
			warn "Did not get an WxMethod for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}
	my $wxframe_mgr = 0;
	if ( exists $args-&gt;{WXFRAME_MGR_TOGGLE} ) {
		$wxframe_mgr = $args-&gt;{WXFRAME_MGR_TOGGLE};
	}
	# require either the use of a wxframe manager or the pointer to the wxframe object
	if ( ! defined $args-&gt;{WXFRAME_OBJ} and !$wxframe_mgr ) {
		if ( DEBUG ) {
			warn "Did not get a WxFrame Object for SignalKey: ".$args-&gt;{SIGNAL_KEY};
		}
		return undef;
	}


	# register within the WXPOEIO hash structure
	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} = {};
	}

	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } = {};
	}

	# Finally store the wx method in the signal key method hash
	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} = {};
	}
	$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS}-&gt;{ $args-&gt;{WX_METHOD} } = 1;

	# set USE_WXFRAME_MGR to falsy as default
	$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR} = 0; 
	if($wxframe_mgr) {
		$_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR} = 1; 
	} else {
		$_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{WXFRAME_OBJ} = $args-&gt;{WXFRAME_OBJ};
	}

	# All registered!
	return 1;
}

# Delete a watcher frame
sub UnRegister_frame {
	# Get the arguments
	my $args = $_[ ARG0 ];

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}
	my $frame = 'DEFAULT';
	if ( exists $args-&gt;{WXFRAME_IDENT} ) {
		$frame = $args-&gt;{WXFRAME_IDENT};
	}
	if ( ! defined $frame ) {
		if ( DEBUG ) {
			warn "Did not get a valid frame name for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}
	if ( ! defined $args-&gt;{WX_METHOD} ) {
		if ( DEBUG ) {
			warn "Did not get an WxMethod for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}

	# Search through the registrations for this specific one
	if ( exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} ) {
		# Scan it for signal key
		if ( exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
			# Scan for the proper event!
			foreach my $evt_meth ( keys %{ $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} } ) {
				if ( $evt_meth eq $args-&gt;{WX_METHOD} ) {
					# Found a match, delete it!
					delete $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS}-&gt;{ $evt_meth };
					if ( scalar keys %{ $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} } == 0 ) {
						delete $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS};
						if ( scalar keys %{ $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } } == 0 ) {
							delete $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} };
							if ( scalar keys %{ $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} } == 0 ) {
								delete $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame};
								if( exists $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR} ) {
									delete $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR};
								}
								if( exists $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{WXFRAME_OBJ} ) {
									delete $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{WXFRAME_OBJ};
								}
								if ( scalar keys %{ $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame} } == 0 ) {
									delete $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame};
								}
							}
						}
					}

					# Return success
					return 1;
				}
			}
		}
	}

	# Found nothing...
	return undef;
}

# Register a frame to receive a signal on the FRAME_TO_FRAME channel (minimal latency between receipt and delivery)
sub Register_frame_to_frame {
	# Get the arguments
	my $args = $_[ ARG0 ];

	# Validation - silently ignore errors
	if ( ! defined $args-&gt;{SIGNAL_KEY} ) {
		if ( DEBUG ) {
			warn 'Did not get any arguments';
		}
		return undef;
	}
	my $frame = 'DEFAULT';
	if ( exists $args-&gt;{WXFRAME_IDENT} ) {
		$frame = $args-&gt;{WXFRAME_IDENT};
	}
	if ( ! defined $frame ) {
		if ( DEBUG ) {
			warn "Did not get a valid frame name for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}
	if ( ! defined $args-&gt;{WX_METHOD} ) {
		if ( DEBUG ) {
			warn "Did not get an WxMethod for SignalKey: ".$args-&gt;{SIGNAL_KEY}." and wxFrame Object: ".$args-&gt;{WXFRAME_OBJ};
		}
		return undef;
	}
	my $wxframe_mgr = 0;
	if ( exists $args-&gt;{WXFRAME_MGR_TOGGLE} ) {
		$wxframe_mgr = $args-&gt;{WXFRAME_MGR_TOGGLE};
	}
	# require either the use of a wxframe manager or the pointer to the wxframe object
	if ( ! defined $args-&gt;{WXFRAME_OBJ} and !$wxframe_mgr ) {
		if ( DEBUG ) {
			warn "Did not get a WxFrame Object for SignalKey: ".$args-&gt;{SIGNAL_KEY};
		}
		return undef;
	}

	# register within the WXPOEIO hash structure
	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame} = {};
	}

	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} } = {};
	}

	# Finally store the wx method in the signal key method hash
	if ( ! exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} ) {
		$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS} = {};
	}
	$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WX_METHODS}-&gt;{ $args-&gt;{WX_METHOD} } = 1;

	# set USE_WXFRAME_MGR to falsy as default
	$_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR} = 0; 
	if($wxframe_mgr) {
		$_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{USE_WXFRAME_MGR} = 1; 
	} else {
		$_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$frame}-&gt;{WXFRAME_OBJ} = $args-&gt;{WXFRAME_OBJ};
	}

	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{WXPOEIO_CHANNEL} = 'FRAME_TO_FRAME';
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $args-&gt;{SIGNAL_KEY} }-&gt;{LATCH} = 0;
	if ( !exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{FRAME_TO_FRAME} ) {
		$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{FRAME_TO_FRAME} = {};
	}

	# All registered!
	return 1;
}

# Where the work is queued...
sub trigger_signals {

	if ( exists $_[HEAP]-&gt;{WXPOEIO_QUEUE} ) {
		my $sq = $_[HEAP]-&gt;{WXPOEIO_QUEUE};
		if($sq!~/ARRAY/i) {
			if ( DEBUG ) {
				warn "The siqnal queue pointer is corrupt: [$sq]. Will not trigger signals";
			}
			return undef;
		}
		while( scalar(@$sq) ) {
			my $signal = shift @$sq;

			if($signal!~/HASH/i) {
				if ( DEBUG ) {
					warn "The siqnal hash pointer is corrupt: [$signal]. Cannot determine signal key and value";
				}
				next;
			}
			foreach my $sigkey (keys %$signal) {
				my $sigvalue = $signal-&gt;{$sigkey};
				if( !exists $_[HEAP]-&gt;{SIGNAL_KEYS}-&gt;{$sigkey}) {
					# warn...a potential configuration error
					warn "No SIGNAL_KEY for [$sigkey] in SIGNAL_KEY hash! Check signal key settings";
					next;
				}
				if( exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{FRAME_TO_FRAME}) {
					# check signal key against FRAME_TO_FRAME channel
					if($_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WXPOEIO_CHANNEL} eq 'FRAME_TO_FRAME') {
						$_[KERNEL]-&gt;yield('TO_WX', $sigkey, $sigvalue);
						next;
					}
				}
				$_[KERNEL]-&gt;yield('TO_POE', $sigkey, $sigvalue);
			}
			if(!scalar(@$sq)) {
				last;
			}
		}
		# signal queue is empty!
		return 1;
	}
	# silently fail falsy...tho, some notice should be given
	return 0;
}
	
# Where the work is done...
sub toPoe {
	# ARG0 = signal_key, ARG1 = signal_value
	my( $sigkey, $sigvalue ) = @_[ ARG0, ARG1 ];

	# Search for this signal!
	if ( exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $sigkey } ) {

		# Test for signal latch
		# (latching restricts follow on signal calls until task has been completed)

		# Test for whether a latch has been specified for the signal call
		if ( !exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH} or !$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH} ) {
			$_[KERNEL]-&gt;yield('_MANAGE_TO_POE', $sigkey, $sigvalue);
			return 1;
		}
		
		# Latching is expected
		# Test for whether the signal call has been latched
		if ( !exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED}  or !$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED}) {
			# no latch; set latch and continue to POE
			$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED} = 1;
			$_[KERNEL]-&gt;yield('_MANAGE_TO_POE', $sigkey, $sigvalue);
			return 1;
		}

		$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WAIT_LATCH} = 1;
		$_[KERNEL]-&gt;yield('_WAIT_ON_LATCH', $sigkey, $sigvalue);

	} else {
		# Ignore this signalkey
		if ( DEBUG ) {
			warn "Got this Signal_key: [$sigkey] -&gt; Ignoring it because it is not registered";
		}
	}

	# All done!
	return 1;
}

# Where the work is finished...
sub end_signal {
	# ARG0 = signal_key, ARG1 = signal_value, [Optional, ARG2 = _wxframe_manager]
	my( $sigkey, $sigvalue, $_wfmgr ) = @_[ ARG0, ARG1, ARG2 ];

	# Search for this signal!
	if ( exists $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $sigkey } ) {

		# clear all latch, locks and noise for signal
		my $channel = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WXPOEIO_CHANNEL};

		$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED} = 0;
		$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_LOCKED} = 0;

		if ( exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE}-&gt;{$sigkey} ) {
			delete $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE}-&gt;{$sigkey};
		}
		
		if ( scalar keys %{ $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE} } == 0 ) {
			$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_NOISY} = 0;
		}
	} else {
		if ( DEBUG ) {
			warn "Terminating an unregistered signal. Opps! [$sigkey]";
		}
	}
	
	if( defined $_wfmgr) {
		$_[KERNEL]-&gt;yield('TO_WX', $sigkey, $sigvalue, $_wfmgr);
	} else {
		$_[KERNEL]-&gt;yield('TO_WX', $sigkey, $sigvalue);
	}
	# signal set to wxframe, close loop
	return 1;
}

# Where EVEN MORE work is done...
sub toWx {
	# ARG0 = signal_key, ARG1 = signal_value, [Optional, ARG2 = _wxframe_manager]
	my( $sigkey, $sigvalue, $_wfmgr ) = @_[ ARG0, ARG1, ARG2 ];

	# Search through the registrations for this specific one
	foreach my $wxframe ( keys %{ $_[HEAP]-&gt;{WXFRAMEIO} } ) {
		# Scan frame key for signal key
		if ( exists $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$wxframe}-&gt;{$sigkey} ) {
			# Scan for the proper evt_method!
			foreach my $evt_meth ( keys %{ $_[HEAP]-&gt;{WXFRAMEIO}-&gt;{$wxframe}-&gt;{$sigkey}-&gt;{WX_METHODS} } ) {

				if ( exists $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$wxframe}-&gt;{USE_WXFRAME_MGR} ) {
					$_wfmgr-&gt;$evt_meth( $sigkey,$sigvalue );
					return 1;
				}
				if ( exists $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$wxframe}-&gt;{WXFRAME_OBJ} ) {
					my $wxframe_obj = $_[HEAP]-&gt;{WXFRAMEIO_WXSIGHANDLE}-&gt;{$wxframe}-&gt;{WXFRAME_OBJ};
					$wxframe_obj-&gt;$evt_meth( $sigkey,$sigvalue );
#					return 1;
				}
				## else, fail silently...nothing is return to the wxframe
			}
		}
	}
	return 1;
}

# manage the latching here
sub _manage_latching {
	# ARG0 = signal_key, ARG1 = signal_value
	my( $sigkey, $sigvalue ) = @_[ ARG0, ARG1 ];

	if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED}  and $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{IS_LATCHED}) {
		my $latches = 0;
		my $timeout = 0;
		if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH_ATTEMPTS} ) {
			$latches = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH_ATTEMPTS};
		}
		if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{TIMEOUT} ) {
			$timeout = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{TIMEOUT};
		}
		if( $latches &gt; $timeout ) {
			# reset latch state and continue to Poe
			$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WAIT_LATCH} = 0;
			$_[KERNEL]-&gt;yield('_WAIT_ON_LATCH', $sigkey, $sigvalue);
			return;
		}
		$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH_ATTEMPTS} = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH_ATTEMPTS} + 1;
		$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WAIT_LATCH} = 1;
		$_[KERNEL]-&gt;yield('_WAIT_ON_LATCH', $sigkey, $sigvalue);
		return;
	}
	$_[KERNEL]-&gt;yield('_MANAGE_TO_POE', $sigkey, $sigvalue);
	return;
}

# activate kernel call to the session here
sub _manage_to_poe {
	# ARG0 = signal_key, ARG1 = signal_value
	my( $sigkey, $sigvalue ) = @_[ ARG0, ARG1 ];

	# if signal requires a channel lock, check on lock and channel use (noise)
	my $channel = 'MAIN'; # default
	if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WXPOEIO_CHANNEL}  and $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WXPOEIO_CHANNEL}) {
		$channel = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WXPOEIO_CHANNEL};
	}
	if(!$channel) {
		# rats...something broke
		if ( DEBUG ) {
			warn "Darn! Looks like the channel value is null. Please fix!";
		}
		return undef;
	}
	if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{LOCK}  and $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{LOCK}) {
		my $lock = 0;
		if ( exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_LOCKED}  and $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_LOCKED}) {
			$lock = 1;
		}
		if ( exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_NOISY}  and $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_NOISY}) {
			$lock = 1;
		}
		if($lock) {
			if ( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRIES}  and $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRIES}) {
				if ( !exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS}) {
					$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS} = 0;
				}
				if( $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS} &lt; $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRIES} ) {
					$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS} = $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS} + 1;
					$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WAIT_LOCK} = 1;
					$_[KERNEL]-&gt;delay('_WAIT_TO_POE' =&gt; 1, $sigkey, $sigvalue);
				}
				# retry unsuccessful, return falsy
				return 0;
			}
		} else {
			$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WAIT_LOCK} = 0;
			$_[KERNEL]-&gt;delay('_WAIT_TO_POE' =&gt; undef, $sigkey, $sigvalue);
			$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{RETRY_ATTEMPTS} = 0;
			$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_LOCKED} = 1;
#			return;
		}
	}
	$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_NOISY} = 1;
	$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE}-&gt;{$sigkey} = 1;

	my $valid_sessions = 0;
	# Now, loop over each targetsession, checking if it is valid
	foreach my $TargetSession ( keys %{ $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $sigkey } } ) {
		# Find out if this session exists
		my $PSession = undef;
		if ( ! $_[KERNEL]-&gt;ID_id_to_session( $TargetSession ) ) {
			# rats...:)
			if ( DEBUG ) {
				warn "TargetSession ID $TargetSession does not exist";
			}
			# but also test for an alias session name
			if(defined $_[KERNEL]-&gt;alias_resolve($TargetSession)) {
				my $ts = $_[KERNEL]-&gt;alias_resolve($TargetSession);
				$PSession = $_[KERNEL]-&gt;ID_session_to_id( $ts );
				if ( DEBUG ) {
					warn "Alias TargetSession ID [$PSession] has been found";
				}
			}
		} else {
			$PSession = $TargetSession;
		}
		# Find event methods to dispatch
		foreach my $evt_meth ( keys %{ $_[HEAP]-&gt;{WXPOEIO}-&gt;{ $sigkey }-&gt;{ $TargetSession } } ) {
			# We call event methods with 2 arguments
			# ARG0 -&gt; SIGNAL_KEY
			# ARG1 -&gt; SIGNAL_VALUE (message)
			$_[KERNEL]-&gt;post(	$PSession,
								$evt_meth,
								$sigkey,
								$sigvalue,
					);
			$valid_sessions++;
		}
	}
	if($valid_sessions) {
		# Return success
		return 1;
	}

	# no signals sent, so fix settings and return falsy...
	$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{IS_LATCHED} = 0;
	if ( exists $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE}-&gt;{$sigkey} ) {
		delete $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE}-&gt;{$sigkey};
	}
	if ( scalar keys %{ $_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{NOISE} } == 0 ) {
		$_[HEAP]-&gt;{WXPOEIO_CHANNELS}-&gt;{$channel}-&gt;{IS_NOISY} = 0;
	}
	return 0;
}

# wait kernel call to session here
sub _wait_to_poe {
	# ARG0 = signal_key, ARG1 = signal_value
	my( $sigkey, $sigvalue ) = @_[ ARG0, ARG1 ];

	if( exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WAIT_LOCK} and $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{ $sigkey }-&gt;{WAIT_LOCK}) {
		$_[KERNEL]-&gt;delay('_MANAGE_TO_POE' =&gt; 1, $sigkey, $sigvalue);
		return 1;
	}
	return 1;
}

# timeout latch here
sub _wait_on_latch {
	# ARG0 = signal_key, ARG1 = signal_value
	my( $sigkey, $sigvalue ) = @_[ ARG0, ARG1 ];

	if( !exists $_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WAIT_LATCH} and !$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{WAIT_LATCH}) {
		$_[HEAP]-&gt;{SIGNAL_KEY_HREF}-&gt;{$sigkey}-&gt;{LATCH_ATTEMPTS} = 0;
		$_[KERNEL]-&gt;yield('_MANAGE_TO_POE', $sigkey, $sigvalue);
		$_[KERNEL]-&gt;delay('_MANAGE_LATCHING' =&gt; undef, $sigkey, $sigvalue);
		return 1;
	}
	$_[KERNEL]-&gt;delay('_MANAGE_LATCHING' =&gt; 1, $sigkey, $sigvalue);
	return 1;
}

# Starts the WxPoe IO
sub StartIO {
	# Create an alias for ourself
	$_[KERNEL]-&gt;alias_set( $_[HEAP]-&gt;{'ALIAS'} );

	# All done!
	return 1;
}

# Stops the WxPoe IO
sub StopIO {
	# Remove our alias
	$_[KERNEL]-&gt;alias_remove( $_[HEAP]-&gt;{'ALIAS'} );

	# Clear our data
	delete $_[HEAP]-&gt;{'WXPOEIO'};
	delete $_[HEAP]-&gt;{'WXFRAMEIO'};

	# All done!
	return 1;
}

sub export_queue_ptr {
	my $queue_var = $_[ ARG0 ];
	if(!exists $_[HEAP]-&gt;{WXPOEIO_QUEUE}) {
		$_[HEAP]-&gt;{WXPOEIO_QUEUE} = [];
	}
	$queue_var = $_[HEAP]-&gt;{WXPOEIO_QUEUE};
	return 1;
}

# End of module
1;
</pre></body></html>