… | |
… | |
156 | handle_asyncs (); |
156 | handle_asyncs (); |
157 | else |
157 | else |
158 | old_sighandler (signum, si, sarg); |
158 | old_sighandler (signum, si, sarg); |
159 | } |
159 | } |
160 | #else |
160 | #else |
161 | static Signal_t async_sighandler (int) |
161 | static Signal_t async_sighandler (int signum) |
162 | { |
162 | { |
163 | if (signum == 9) |
163 | if (signum == 9) |
164 | a_asyncssync_handle (); |
164 | handle_asyncs (); |
165 | else |
165 | else |
166 | old_sighandler (signum); |
166 | old_sighandler (signum); |
167 | } |
167 | } |
168 | #endif |
168 | #endif |
169 | |
169 | |
|
|
170 | static void |
|
|
171 | scope_block_cb (pTHX_ void *async_sv) |
|
|
172 | { |
|
|
173 | struct async *async = INT2PTR (struct async *, SvIVX ((SV *)async_sv)); |
|
|
174 | |
|
|
175 | --async->blocked; |
|
|
176 | if (async->pending && !async->blocked) |
|
|
177 | handle_async (async); |
|
|
178 | |
|
|
179 | SvREFCNT_dec (async_sv); |
|
|
180 | } |
170 | |
181 | |
171 | MODULE = Async::Interrupt PACKAGE = Async::Interrupt |
182 | MODULE = Async::Interrupt PACKAGE = Async::Interrupt |
172 | |
183 | |
173 | BOOT: |
184 | BOOT: |
174 | old_sighandler = PL_sighandlerp; |
185 | old_sighandler = PL_sighandlerp; |
175 | PL_sighandlerp = async_sighandler; |
186 | PL_sighandlerp = async_sighandler; |
176 | sig_pending = &PL_sig_pending; |
187 | sig_pending = &PL_sig_pending; |
177 | psig_pend = PL_psig_pend; |
188 | psig_pend = PL_psig_pend; |
178 | asyncs = newAV (); |
189 | asyncs = newAV (); |
|
|
190 | CvNODEBUG_on (get_cv ("Async::Interrupt::scope_block", 0)); /* otherwise calling scope can be the debugger */ |
|
|
191 | |
|
|
192 | PROTOTYPES: DISABLE |
179 | |
193 | |
180 | SV * |
194 | SV * |
181 | _alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w) |
195 | _alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w) |
182 | CODE: |
196 | CODE: |
183 | { |
197 | { |
… | |
… | |
226 | unblock (SV *self) |
240 | unblock (SV *self) |
227 | CODE: |
241 | CODE: |
228 | { |
242 | { |
229 | struct async *async = INT2PTR (struct async *, SvIVX (SvRV (self))); |
243 | struct async *async = INT2PTR (struct async *, SvIVX (SvRV (self))); |
230 | --async->blocked; |
244 | --async->blocked; |
231 | |
|
|
232 | if (async->pending && !async->blocked) |
245 | if (async->pending && !async->blocked) |
233 | handle_async (async); |
246 | handle_async (async); |
|
|
247 | } |
|
|
248 | |
|
|
249 | void |
|
|
250 | scope_block (SV *self) |
|
|
251 | CODE: |
|
|
252 | { |
|
|
253 | SV *async_sv = SvRV (self); |
|
|
254 | struct async *async = INT2PTR (struct async *, SvIVX (async_sv)); |
|
|
255 | ++async->blocked; |
|
|
256 | |
|
|
257 | LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */ |
|
|
258 | SAVEDESTRUCTOR_X (scope_block_cb, (void *)SvREFCNT_inc (async_sv)); |
|
|
259 | ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */ |
234 | } |
260 | } |
235 | |
261 | |
236 | void |
262 | void |
237 | DESTROY (SV *self) |
263 | DESTROY (SV *self) |
238 | CODE: |
264 | CODE: |
… | |
… | |
243 | |
269 | |
244 | for (i = AvFILLp (asyncs); i >= 0; --i) |
270 | for (i = AvFILLp (asyncs); i >= 0; --i) |
245 | if (AvARRAY (asyncs)[i] == async_sv) |
271 | if (AvARRAY (asyncs)[i] == async_sv) |
246 | { |
272 | { |
247 | if (i < AvFILLp (asyncs)) |
273 | if (i < AvFILLp (asyncs)) |
248 | AvARRAY (asyncs)[i] == AvARRAY (asyncs)[AvFILLp (asyncs)]; |
274 | AvARRAY (asyncs)[i] = AvARRAY (asyncs)[AvFILLp (asyncs)]; |
249 | |
275 | |
250 | assert (av_pop (asyncs) == async_sv); |
276 | assert (av_pop (asyncs) == async_sv); |
251 | goto found; |
277 | goto found; |
252 | } |
278 | } |
253 | |
279 | |