ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Async-Interrupt/Interrupt.pm
(Generate patch)

Comparing cvsroot/Async-Interrupt/Interrupt.pm (file contents):
Revision 1.17 by root, Tue Jul 28 01:19:44 2009 UTC vs.
Revision 1.19 by root, Tue Jul 28 13:17:05 2009 UTC

91I<running> interpreter, there is optional support for signalling a pipe 91I<running> interpreter, there is optional support for signalling a pipe
92- that means you can also wait for the pipe to become readable (e.g. via 92- that means you can also wait for the pipe to become readable (e.g. via
93L<EV> or L<AnyEvent>). This, of course, incurs the overhead of a C<read> 93L<EV> or L<AnyEvent>). This, of course, incurs the overhead of a C<read>
94and C<write> syscall. 94and C<write> syscall.
95 95
96=head1 USAGE EXAMPLES
97
98=head2 Implementing race-free signal handling
99
100This example uses a single event pipe for all signals, and one
101Async::Interrupt per signal. This code is actually what the L<AnyEvent>
102module uses itself when Async::Interrupt is available.
103
104First, create the event pipe and hook it into the event loop
105
106 $SIGPIPE = new Async::Interrupt::EventPipe;
107 $SIGPIPE_W = AnyEvent->io (
108 fh => $SIGPIPE->fileno,
109 poll => "r",
110 cb => \&_signal_check, # defined later
111 );
112
113Then, for each signal to hook, create an Async::Interrupt object. The
114callback just sets a global variable, as we are only interested in
115synchronous signals (i.e. when the event loop polls), which is why the
116pipe draining is not done automatically.
117
118 my $interrupt = new Async::Interrupt
119 cb => sub { undef $SIGNAL_RECEIVED{$signum} }
120 signal => $signum,
121 pipe => [$SIGPIPE->filenos],
122 pipe_autodrain => 0,
123 ;
124
125Finally, the I/O callback for the event pipe handles the signals:
126
127 sub _signal_check {
128 # drain the pipe first
129 $SIGPIPE->drain;
130
131 # two loops, just to be sure
132 while (%SIGNAL_RECEIVED) {
133 for (keys %SIGNAL_RECEIVED) {
134 delete $SIGNAL_RECEIVED{$_};
135 warn "signal $_ received\n";
136 }
137 }
138 }
139
140=head2 Interrupt perl from another thread
141
142This example interrupts the Perl interpreter from another thread, via the
143XS API. This is used by e.g. the L<EV::Loop::Async> module.
144
145#TODO#
146
96=head1 THE Async::Interrupt CLASS 147=head1 THE Async::Interrupt CLASS
97 148
98=over 4 149=over 4
99 150
100=cut 151=cut
103 154
104use common::sense; 155use common::sense;
105 156
106BEGIN { 157BEGIN {
107 # the next line forces initialisation of internal 158 # the next line forces initialisation of internal
108 # signal handling # variables 159 # signal handling variables, otherwise, PL_sig_pending
160 # etc. will be null pointers.
109 $SIG{KILL} = sub { }; 161 $SIG{KILL} = sub { };
110 162
111 our $VERSION = '0.6'; 163 our $VERSION = '1.0';
112 164
113 require XSLoader; 165 require XSLoader;
114 XSLoader::load ("Async::Interrupt", $VERSION); 166 XSLoader::load ("Async::Interrupt", $VERSION);
115} 167}
116 168
139The exceptions are C<$!> and C<$@>, which are saved and restored by 191The exceptions are C<$!> and C<$@>, which are saved and restored by
140Async::Interrupt. 192Async::Interrupt.
141 193
142If the callback should throw an exception, then it will be caught, 194If the callback should throw an exception, then it will be caught,
143and C<$Async::Interrupt::DIED> will be called with C<$@> containing 195and C<$Async::Interrupt::DIED> will be called with C<$@> containing
144the exception. The default will simply C<warn> about the message and 196the exception. The default will simply C<warn> about the message and
145continue. 197continue.
146 198
147=item c_cb => [$c_func, $c_arg] 199=item c_cb => [$c_func, $c_arg]
148 200
149Registers a C callback the be invoked whenever the async interrupt is 201Registers a C callback the be invoked whenever the async interrupt is
183the given signal is caught by the process. 235the given signal is caught by the process.
184 236
185Only one async can hook a given signal, and the signal will be restored to 237Only one async can hook a given signal, and the signal will be restored to
186defaults when the Async::Interrupt object gets destroyed. 238defaults when the Async::Interrupt object gets destroyed.
187 239
240=item signal_hysteresis => $boolean
241
242Sets the initial signal hysteresis state, see the C<signal_hysteresis>
243method, below.
244
188=item pipe => [$fileno_or_fh_for_reading, $fileno_or_fh_for_writing] 245=item pipe => [$fileno_or_fh_for_reading, $fileno_or_fh_for_writing]
189 246
190Specifies two file descriptors (or file handles) that should be signalled 247Specifies two file descriptors (or file handles) that should be signalled
191whenever the async interrupt is signalled. This means a single octet will 248whenever the async interrupt is signalled. This means a single octet will
192be written to it, and before the callback is being invoked, it will be 249be written to it, and before the callback is being invoked, it will be
205 262
206If you want to share a single event pipe between multiple Async::Interrupt 263If you want to share a single event pipe between multiple Async::Interrupt
207objects, you can use the C<Async::Interrupt::EventPipe> class to manage 264objects, you can use the C<Async::Interrupt::EventPipe> class to manage
208those. 265those.
209 266
267=item pipe_autodrain => $boolean
268
269Sets the initial autodrain state, see the C<pipe_autodrain> method, below.
270
210=back 271=back
211 272
212=cut 273=cut
213 274
214sub new { 275sub new {
215 my ($class, %arg) = @_; 276 my ($class, %arg) = @_;
216 277
217 bless \(_alloc $arg{cb}, @{$arg{c_cb}}[0,1], @{$arg{pipe}}[0,1], $arg{signal}, $arg{var}), $class 278 my $self = bless \(_alloc $arg{cb}, @{$arg{c_cb}}[0,1], @{$arg{pipe}}[0,1], $arg{signal}, $arg{var}), $class;
279
280 # urgs, reminds me of Event
281 for my $attr (qw(pipe_autodrain signal_hysteresis)) {
282 $self->$attr ($arg{$attr}) if exists $arg{$attr};
283 }
284
285 $self
218} 286}
219 287
220=item ($signal_func, $signal_arg) = $async->signal_func 288=item ($signal_func, $signal_arg) = $async->signal_func
221 289
222Returns the address of a function to call asynchronously. The function 290Returns the address of a function to call asynchronously. The function
376This only works when the pipe was created by Async::Interrupt. 444This only works when the pipe was created by Async::Interrupt.
377 445
378Async::Interrupt ensures that the reading file descriptor does not change 446Async::Interrupt ensures that the reading file descriptor does not change
379it's value. 447it's value.
380 448
449=item $signum = Async::Interrupt::sig2num $signame_or_number
450
451=item $signame = Async::Interrupt::sig2name $signame_or_number
452
453These two convenience functions simply convert a signal name or number to
454the corresponding name or number. They are not used by this module and
455exist just because perl doesn't have a nice way to do this on its own.
456
457They will return C<undef> on illegal names or numbers.
458
381=back 459=back
382 460
383=head1 THE Async::Interrupt::EventPipe CLASS 461=head1 THE Async::Interrupt::EventPipe CLASS
384 462
385Pipes are the predominent utility to make asynchronous signals 463Pipes are the predominent utility to make asynchronous signals

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines