1# You may distribute under the terms of either the GNU General Public License 2# or the Artistic License (the same terms as Perl itself) 3# 4# (C) Paul Evans, 2009-2011 -- leonerd@leonerd.org.uk 5 6package IO::Async::Signal; 7 8use strict; 9use warnings; 10use base qw( IO::Async::Notifier ); 11 12our $VERSION = '0.800'; 13 14use Carp; 15 16=head1 NAME 17 18C<IO::Async::Signal> - event callback on receipt of a POSIX signal 19 20=head1 SYNOPSIS 21 22 use IO::Async::Signal; 23 24 use IO::Async::Loop; 25 my $loop = IO::Async::Loop->new; 26 27 my $signal = IO::Async::Signal->new( 28 name => "HUP", 29 30 on_receipt => sub { 31 print "I caught SIGHUP\n"; 32 }, 33 ); 34 35 $loop->add( $signal ); 36 37 $loop->run; 38 39=head1 DESCRIPTION 40 41This subclass of L<IO::Async::Notifier> invokes its callback when a particular 42POSIX signal is received. 43 44Multiple objects can be added to a C<Loop> that all watch for the same signal. 45The callback functions will all be invoked, in no particular order. 46 47=cut 48 49=head1 EVENTS 50 51The following events are invoked, either using subclass methods or CODE 52references in parameters: 53 54=head2 on_receipt 55 56Invoked when the signal is received. 57 58=cut 59 60=head1 PARAMETERS 61 62The following named parameters may be passed to C<new> or C<configure>: 63 64=head2 name => STRING 65 66The name of the signal to watch. This should be a bare name like C<TERM>. Can 67only be given at construction time. 68 69=head2 on_receipt => CODE 70 71CODE reference for the C<on_receipt> event. 72 73Once constructed, the C<Signal> will need to be added to the C<Loop> before it 74will work. 75 76=cut 77 78sub _init 79{ 80 my $self = shift; 81 my ( $params ) = @_; 82 83 my $name = delete $params->{name} or croak "Expected 'name'"; 84 85 $name =~ s/^SIG//; # Trim a leading "SIG" 86 87 $self->{name} = $name; 88 89 $self->SUPER::_init( $params ); 90} 91 92sub configure 93{ 94 my $self = shift; 95 my %params = @_; 96 97 if( exists $params{on_receipt} ) { 98 $self->{on_receipt} = delete $params{on_receipt}; 99 100 undef $self->{cb}; # Will be lazily constructed when needed 101 102 if( my $loop = $self->loop ) { 103 $self->_remove_from_loop( $loop ); 104 $self->_add_to_loop( $loop ); 105 } 106 } 107 108 unless( $self->can_event( 'on_receipt' ) ) { 109 croak 'Expected either a on_receipt callback or an ->on_receipt method'; 110 } 111 112 $self->SUPER::configure( %params ); 113} 114 115sub _add_to_loop 116{ 117 my $self = shift; 118 my ( $loop ) = @_; 119 120 $self->{cb} ||= $self->make_event_cb( 'on_receipt' ); 121 122 $self->{id} = $loop->attach_signal( $self->{name}, $self->{cb} ); 123} 124 125sub _remove_from_loop 126{ 127 my $self = shift; 128 my ( $loop ) = @_; 129 130 $loop->detach_signal( $self->{name}, $self->{id} ); 131 undef $self->{id}; 132} 133 134sub notifier_name 135{ 136 my $self = shift; 137 if( length( my $name = $self->SUPER::notifier_name ) ) { 138 return $name; 139 } 140 141 return $self->{name}; 142} 143 144=head1 AUTHOR 145 146Paul Evans <leonerd@leonerd.org.uk> 147 148=cut 149 1500x55AA; 151