Give signal handlers within an object access to $self by
defining them with an anonymous subroutine.
Updated: to reflect additional comments below about
establishing per-object signal handlers.
sub set_signal_handlers {
my $self=shift;
$SIG{USR1}=sub { $self->handler_USR1() }
...
}
sub handler_USR1 {
my $self=shift;
# Now I can access the object through $self
}
And call
$object->set_signal_handlers() after
creating the object (or
$self->set_signal_handlers()
from within the object itself).
As pointed out below, the above technique has the problem that
signal handlers in Unix are per-process, so if more than one
object sets a signal handler for the same signal using the
technique above, only one of
them will be executed. The following code solves this problem
(slightly modified from code below, and combining my code with
chromatic's) by using a single per-class signal handler, and
a hash in which the specific per-object handlers are stored
as code references. When the per-class handler is called, it
calls all the per-object handlers in sequence. I wonder if
this could be declared a belonging to class UNIVERSAL and then
have every object in your program use it :-)
package Obj;
# Class variable
$handlers={};
sub new {
my $class = shift;
my $self = { @_ };
bless $self, $class;
$self->set_signal_handlers;
$self;
}
sub name {
shift->{'name'};
}
sub set_signal_handlers {
my $self = shift;
# Set handlers for USR1
if (!$handlers{USR1}) {
# Class signal handler, only set the first time
$SIG{USR1} = sub { class_handle_signal('USR1'); };
}
# You could index by $self->name, or by any other identifier
$handlers->{USR1}->{$self} = $self->handle_USR1();
# Set handlers for USR1
if (!$handlers{USR2}) {
$SIG{USR2} = sub { class_handle_signal('USR2'); }
}
$handlers->{USR2}->{$self} = $self->handle_USR2();
}
sub handle_USR1 {
my $self = shift;
return sub {
print "handling USR1 for ", $self->name, "\n";
}
}
sub handle_USR2 {
my $self = shift;
return sub {
print "handling USR2 for ", $self->name, "\n";
}
}
sub class_handle_signal {
my $sig=shift;
foreach (keys %{$handlers->{$sig}}) {
&{$handlers->{$sig}->{$_}}();
}
}
package main;
my $obj1 = new Obj(name => 'obj1');
my $obj2 = new Obj(name => 'obj2');
while (1) { }