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

Comparing Async-Interrupt/Interrupt.xs (file contents):
Revision 1.8 by root, Tue Jul 14 19:29:26 2009 UTC vs.
Revision 1.9 by root, Fri Jul 17 01:51:32 2009 UTC

29typedef struct { 29typedef struct {
30 SV *cb; 30 SV *cb;
31 void (*c_cb)(pTHX_ void *c_arg, int value); 31 void (*c_cb)(pTHX_ void *c_arg, int value);
32 void *c_arg; 32 void *c_arg;
33 SV *fh_r, *fh_w; 33 SV *fh_r, *fh_w;
34 SV *value;
34 int signum; 35 int signum;
35 volatile int blocked; 36 volatile int blocked;
36 37
37 int fd_r; 38 s_epipe ep;
38 volatile int fd_w;
39 int fd_wlen; 39 int fd_wlen;
40 atomic_t fd_enable; 40 atomic_t fd_enable;
41 atomic_t value;
42 atomic_t pending; 41 atomic_t pending;
42 volatile IV *valuep;
43} async_t; 43} async_t;
44 44
45static AV *asyncs; 45static AV *asyncs;
46static async_t *sig_async [SIG_SIZE]; 46static async_t *sig_async [SIG_SIZE];
47 47
55 static char pipedata [8]; 55 static char pipedata [8];
56 56
57 async_t *async = (async_t *)signal_arg; 57 async_t *async = (async_t *)signal_arg;
58 int pending = async->pending; 58 int pending = async->pending;
59 59
60 async->value = value; 60 *async->valuep = value ? value : 1;
61 async->pending = 1; 61 async->pending = 1;
62 async_pending = 1; 62 async_pending = 1;
63 psig_pend [9] = 1; 63 psig_pend [9] = 1;
64 *sig_pending = 1; 64 *sig_pending = 1;
65 65
66 { 66 {
67 int fd_w = async->fd_w;
68 int fd_enable = async->fd_enable; 67 int fd_enable = async->fd_enable;
69 68
70 if (!pending && fd_w >= 0 && fd_enable) 69 if (!pending && fd_enable && async->ep.fd [1] >= 0)
71 if (write (fd_w, pipedata, async->fd_wlen) < 0 && errno == EINVAL) 70 s_epipe_signal (&async->ep);
72 /* on EINVAL we assume it's an eventfd */
73 write (fd_w, pipedata, (async->fd_wlen = 8));
74 } 71 }
75} 72}
76 73
77static void 74static void
78handle_async (async_t *async) 75handle_async (async_t *async)
79{ 76{
80 int old_errno = errno; 77 int old_errno = errno;
81 int value = async->value; 78 int value = *async->valuep;
82 79
80 *async->valuep = 0;
83 async->pending = 0; 81 async->pending = 0;
84 82
85 /* drain pipe */ 83 /* drain pipe */
86 if (async->fd_r >= 0 && async->fd_enable) 84 if (async->fd_enable && async->ep.fd [0] >= 0)
87 { 85 s_epipe_drain (&async->ep);
88 char dummy [9]; /* 9 is enough for eventfd and normal pipes */
89
90 while (read (async->fd_r, dummy, sizeof (dummy)) == sizeof (dummy))
91 ;
92 }
93 86
94 if (async->c_cb) 87 if (async->c_cb)
95 { 88 {
96 dTHX; 89 dTHX;
97 async->c_cb (aTHX_ async->c_arg, value); 90 async->c_cb (aTHX_ async->c_arg, value);
208 CvNODEBUG_on (get_cv ("Async::Interrupt::scope_block", 0)); /* otherwise calling scope can be the debugger */ 201 CvNODEBUG_on (get_cv ("Async::Interrupt::scope_block", 0)); /* otherwise calling scope can be the debugger */
209 202
210PROTOTYPES: DISABLE 203PROTOTYPES: DISABLE
211 204
212void 205void
213_alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w, SV *signl) 206_alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w, SV *signl, SV *pvalue)
214 PPCODE: 207 PPCODE:
215{ 208{
216 SV *cv = SvOK (cb) ? SvREFCNT_inc (s_get_cv_croak (cb)) : 0; 209 SV *cv = SvOK (cb) ? SvREFCNT_inc (s_get_cv_croak (cb)) : 0;
217 int fd_r = SvOK (fh_r) ? s_fileno_croak (fh_r, 0) : -1;
218 int fd_w = SvOK (fh_w) ? s_fileno_croak (fh_w, 1) : -1;
219 async_t *async; 210 async_t *async;
220 211
221 Newz (0, async, 1, async_t); 212 Newz (0, async, 1, async_t);
222 213
223 XPUSHs (sv_2mortal (newSViv (PTR2IV (async)))); 214 XPUSHs (sv_2mortal (newSViv (PTR2IV (async))));
215 /* TODO: need to bless right now to ensure deallocation */
224 av_push (asyncs, TOPs); 216 av_push (asyncs, TOPs);
225 217
226 async->fh_r = fd_r >= 0 ? newSVsv (fh_r) : 0; async->fd_r = fd_r; 218 SvGETMAGIC (fh_r); SvGETMAGIC (fh_w);
227 async->fh_w = fd_w >= 0 ? newSVsv (fh_w) : 0; async->fd_w = fd_w; 219 if (SvOK (fh_r) || SvOK (fh_w))
220 {
221 int fd_r = s_fileno_croak (fh_r, 0);
222 int fd_w = s_fileno_croak (fh_w, 1);
223
224 async->fh_r = newSVsv (fh_r);
225 async->fh_w = newSVsv (fh_w);
226 async->ep.fd [0] = fd_r;
227 async->ep.fd [1] = fd_w;
228 async->fd_wlen = 1; 228 async->ep.len = 1;
229 async->fd_enable = 1; 229 async->fd_enable = 1;
230 }
231
232 async->value = SvROK (pvalue)
233 ? SvREFCNT_inc_NN (SvRV (pvalue))
234 : NEWSV (0, 0);
235
236 sv_setiv (async->value, 0);
237 SvIOK_only (async->value); /* just to be sure */
238 SvREADONLY_on (async->value);
239
240 async->valuep = &(SvIVX (async->value));
241
230 async->cb = cv; 242 async->cb = cv;
231 async->c_cb = c_cb; 243 async->c_cb = c_cb;
232 async->c_arg = c_arg; 244 async->c_arg = c_arg;
233 async->signum = SvOK (signl) ? s_signum_croak (signl) : 0; 245 async->signum = SvOK (signl) ? s_signum_croak (signl) : 0;
234 246
256 PPCODE: 268 PPCODE:
257 EXTEND (SP, 2); 269 EXTEND (SP, 2);
258 PUSHs (sv_2mortal (newSViv (PTR2IV (async_signal)))); 270 PUSHs (sv_2mortal (newSViv (PTR2IV (async_signal))));
259 PUSHs (sv_2mortal (newSViv (PTR2IV (async)))); 271 PUSHs (sv_2mortal (newSViv (PTR2IV (async))));
260 272
273IV
274c_var (async_t *async)
275 CODE:
276 RETVAL = PTR2IV (async->valuep);
277 OUTPUT:
278 RETVAL
279
261void 280void
262signal (async_t *async, int value = 0) 281signal (async_t *async, int value = 1)
263 CODE: 282 CODE:
264 async_signal (async, value); 283 async_signal (async, value);
265 284
266void 285void
267block (async_t *async) 286block (async_t *async)
291 ALIAS: 310 ALIAS:
292 pipe_enable = 1 311 pipe_enable = 1
293 pipe_disable = 0 312 pipe_disable = 0
294 CODE: 313 CODE:
295 async->fd_enable = ix; 314 async->fd_enable = ix;
315
316int
317pipe_fileno (async_t *async)
318 CODE:
319 if (!async->ep.len)
320 {
321 int res;
322
323 /*block (async);*//*TODO*/
324 res = s_epipe_new (&async->ep);
325 async->fd_enable = 1;
326 /*unblock (async);*//*TODO*/
327
328 if (res < 0)
329 croak ("Async::Interrupt: unable to initialize event pipe");
330 }
331
332 RETVAL = async->ep.fd [0];
333 OUTPUT:
334 RETVAL
335
336
337void
338post_fork (async_t *async)
339 CODE:
340 if (async->ep.len)
341 {
342 int res;
343
344 /*block (async);*//*TODO*/
345 res = s_epipe_renew (&async->ep);
346 /*unblock (async);*//*TODO*/
347
348 if (res < 0)
349 croak ("Async::Interrupt: unable to initialize event pipe after fork");
350 }
296 351
297void 352void
298DESTROY (SV *self) 353DESTROY (SV *self)
299 CODE: 354 CODE:
300{ 355{
328 sigaction (async->signum, &sa, 0); 383 sigaction (async->signum, &sa, 0);
329 } 384 }
330#endif 385#endif
331 } 386 }
332 387
388 if (!async->fh_r && async->ep.len)
389 s_epipe_destroy (&async->ep);
390
333 SvREFCNT_dec (async->fh_r); 391 SvREFCNT_dec (async->fh_r);
334 SvREFCNT_dec (async->fh_w); 392 SvREFCNT_dec (async->fh_w);
335 SvREFCNT_dec (async->cb); 393 SvREFCNT_dec (async->cb);
394 SvREFCNT_dec (async->value);
336 395
337 Safefree (async); 396 Safefree (async);
338} 397}
339 398

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines