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.1 by root, Thu Jul 2 13:41:44 2009 UTC vs.
Revision 1.2 by root, Thu Jul 2 15:13:03 2009 UTC

39 39
40static AV *asyncs; 40static AV *asyncs;
41 41
42struct async { 42struct async {
43 SV *cb; 43 SV *cb;
44 void (*c_cb)(pTHX_ void *c_data, int value); 44 void (*c_cb)(pTHX_ void *c_arg, int value);
45 void *c_data; 45 void *c_arg;
46 SV *fh; 46 SV *fh_r, *fh_w;
47 int blocked;
47 48
48 int fd; 49 int fd_r, fd_w;
49 atomic_t value; 50 atomic_t value;
50 atomic_t signalled; 51 atomic_t pending;
51}; 52};
52 53
53/* the main workhorse to signal */ 54/* the main workhorse to signal */
54static void 55static void
55async_signal (void *signal_arg, int value) 56async_signal (void *signal_arg, int value)
56{ 57{
57 struct async *async = (struct async *)signal_arg; 58 struct async *async = (struct async *)signal_arg;
59 int pending = async->pending;
58 60
59 async->value = value; 61 async->value = value;
60 62 async->pending = 1;
61 if (!async->signalled)
62 {
63 async->signalled = 1;
64
65 if (async->fd >= 0)
66 write (async->fd, async, 1);
67 }
68
69 async_pending = 1; 63 async_pending = 1;
70 psig_pend [9] = 1; 64 psig_pend [9] = 1;
71 *sig_pending = 1; 65 *sig_pending = 1;
66
67 if (!pending && async->fd_w >= 0)
68 write (async->fd_w, async, 1);
72} 69}
73 70
74static void 71static void
75async_handle (void) 72handle_async (struct async *async)
76{ 73{
74 int old_errno = errno;
75 int value = async->value;
76
77 async->pending = 0;
78
79 /* drain pipe */
80 if (async->fd_r >= 0)
81 {
82 char dummy [4];
83
84 while (read (async->fd_r, dummy, sizeof (dummy)) == sizeof (dummy))
85 ;
86 }
87
88 if (async->c_cb)
89 {
90 dTHX;
91 async->c_cb (aTHX_ async->c_arg, value);
92 }
93
94 if (async->cb)
95 {
96 dSP;
97
98 SV *saveerr = SvOK (ERRSV) ? sv_mortalcopy (ERRSV) : 0;
99 SV *savedie = PL_diehook;
100
101 PL_diehook = 0;
102
103 PUSHSTACKi (PERLSI_SIGNAL);
104
105 PUSHMARK (SP);
106 XPUSHs (sv_2mortal (newSViv (value)));
107 PUTBACK;
108 call_sv (async->cb, G_VOID | G_DISCARD | G_EVAL);
109
110 if (SvTRUE (ERRSV))
111 {
112 SPAGAIN;
113
114 PUSHMARK (SP);
115 PUTBACK;
116 call_sv (get_sv ("Async::Interrupt::DIED", 1), G_VOID | G_DISCARD | G_EVAL | G_KEEPERR);
117
118 sv_setpvn (ERRSV, "", 0);
119 }
120
121 if (saveerr)
122 sv_setsv (ERRSV, saveerr);
123
124 {
125 SV *oldhook = PL_diehook;
126 PL_diehook = savedie;
127 SvREFCNT_dec (oldhook);
128 }
129
130 POPSTACK;
131 }
132
133 errno = old_errno;
134}
135
136static void
137handle_asyncs (void)
138{
139 int i;
140
77 async_pending = 0; 141 async_pending = 0;
142
143 for (i = AvFILLp (asyncs); i >= 0; --i)
144 {
145 struct async *async = INT2PTR (struct async *, SvIVX (AvARRAY (asyncs)[i]));
146
147 if (async->pending && !async->blocked)
148 handle_async (async);
149 }
78} 150}
79 151
80#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) 152#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
81static Signal_t async_sighandler (int signum, siginfo_t *si, void *sarg) 153static Signal_t async_sighandler (int signum, siginfo_t *si, void *sarg)
82{ 154{
83 if (signum == 9) 155 if (signum == 9)
84 async_handle (); 156 handle_asyncs ();
85 else 157 else
86 old_sighandler (signum, si, sarg); 158 old_sighandler (signum, si, sarg);
87} 159}
88#else 160#else
89static Signal_t async_sighandler (int) 161static Signal_t async_sighandler (int)
90{ 162{
91 if (signum == 9) 163 if (signum == 9)
92 async_handle (); 164 a_asyncssync_handle ();
93 else 165 else
94 old_sighandler (signum); 166 old_sighandler (signum);
95} 167}
96#endif 168#endif
97 169
104 sig_pending = &PL_sig_pending; 176 sig_pending = &PL_sig_pending;
105 psig_pend = PL_psig_pend; 177 psig_pend = PL_psig_pend;
106 asyncs = newAV (); 178 asyncs = newAV ();
107 179
108SV * 180SV *
109_alloc (SV *cb, void *c_cb, void *c_data, SV *fh) 181_alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w)
110 CODE: 182 CODE:
111{ 183{
112 SV *cv = SvOK (cb) ? SvREFCNT_inc_NN (get_cb (cb)) : 0; 184 SV *cv = SvOK (cb) ? SvREFCNT_inc_NN (get_cb (cb)) : 0;
185 int fd_r = SvOK (fh_r) ? extract_fd (fh_r, 0) : -1;
113 int fd = SvOK (fh) ? extract_fd (fh, 1) : -1; 186 int fd_w = SvOK (fh_w) ? extract_fd (fh_w, 1) : -1;
114
115 struct async *async; 187 struct async *async;
188
116 Newz (0, async, 1, struct async); 189 Newz (0, async, 1, struct async);
117 190
118 async->fh = fd >= 0 ? newSVsv (fh) : 0; 191 async->fh_r = fd_r >= 0 ? newSVsv (fh_r) : 0; async->fd_r = fd_r;
119 async->fd = fd; 192 async->fh_w = fd_w >= 0 ? newSVsv (fh_w) : 0; async->fd_w = fd_w;
120 async->cb = cb; 193 async->cb = cv;
121 async->c_cb = c_cb; 194 async->c_cb = c_cb;
122 async->c_data = c_data; 195 async->c_arg = c_arg;
196
197 printf ("r,w %d,%d\n", fd_r, fd_w);//D
123 198
124 RETVAL = newSViv (PTR2IV (async)); 199 RETVAL = newSViv (PTR2IV (async));
125 av_push (asyncs, RETVAL); 200 av_push (asyncs, RETVAL);
126
127 RETVAL = newRV_noinc (RETVAL);
128} 201}
129 OUTPUT: 202 OUTPUT:
130 RETVAL 203 RETVAL
131 204
132void 205void
133signal_cb (SV *self) 206signal_func (SV *self)
134 PPCODE: 207 PPCODE:
135 EXTEND (SP, 2); 208 EXTEND (SP, 2);
136 PUSHs (sv_2mortal (newSViv (PTR2IV (async_signal)))); 209 PUSHs (sv_2mortal (newSViv (PTR2IV (async_signal))));
137 PUSHs (sv_2mortal (newSViv (SvIV (SvRV (self))))); 210 PUSHs (sv_2mortal (newSViv (SvIVX (SvRV (self)))));
138 211
139void 212void
140signal (SV *self, int value = 0) 213signal (SV *self, int value = 0)
141 CODE: 214 CODE:
142 async_signal (INT2PTR (void *, SvIV (SvRV (self))), value); 215 async_signal (INT2PTR (void *, SvIVX (SvRV (self))), value);
216
217void
218block (SV *self)
219 CODE:
220{
221 struct async *async = INT2PTR (struct async *, SvIVX (SvRV (self)));
222 ++async->blocked;
223}
224
225void
226unblock (SV *self)
227 CODE:
228{
229 struct async *async = INT2PTR (struct async *, SvIVX (SvRV (self)));
230 --async->blocked;
231
232 if (async->pending && !async->blocked)
233 handle_async (async);
234}
143 235
144void 236void
145DESTROY (SV *self) 237DESTROY (SV *self)
146 CODE: 238 CODE:
147{ 239{
148 int i; 240 int i;
149 SV *async_sv = SvRV (self); 241 SV *async_sv = SvRV (self);
150 struct async *async = INT2PTR (struct async *, SvIV (async_sv)); 242 struct async *async = INT2PTR (struct async *, SvIVX (async_sv));
151 243
152 for (i = AvFILLp (asyncs); i > 0; --i) 244 for (i = AvFILLp (asyncs); i >= 0; --i)
153 if (AvARRAY (asyncs)[i] == async_sv) 245 if (AvARRAY (asyncs)[i] == async_sv)
154 { 246 {
155 if (i < AvFILLp (asyncs)) 247 if (i < AvFILLp (asyncs))
156 AvARRAY (asyncs)[i] == AvARRAY (asyncs)[AvFILLp (asyncs)]; 248 AvARRAY (asyncs)[i] == AvARRAY (asyncs)[AvFILLp (asyncs)];
157 249
158 assert (av_pop (asyncs) == async_sv); 250 assert (av_pop (asyncs) == async_sv);
159 goto found; 251 goto found;
160 } 252 }
161 253
162 if (!PL_dirty) 254 if (!PL_dirty)
163 warn ("Async::Interrupt::DESTROY could not find async object in list of asyncs, please report!"); 255 warn ("Async::Interrupt::DESTROY could not find async object in list of asyncs, please report");
164 256
165 found: 257 found:
166 SvREFCNT_dec (async->fh); 258 SvREFCNT_dec (async->fh_r);
259 SvREFCNT_dec (async->fh_w);
167 SvREFCNT_dec (async->cb); 260 SvREFCNT_dec (async->cb);
168 261
169 Safefree (async); 262 Safefree (async);
170} 263}
171 264

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines