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

Comparing cvsroot/EV-Loop-Async/Async.xs (file contents):
Revision 1.7 by root, Tue Jul 14 19:39:34 2009 UTC vs.
Revision 1.8 by root, Fri Jul 17 02:52:22 2009 UTC

13 mutex_t lock; /* global loop lock */ 13 mutex_t lock; /* global loop lock */
14 void (*signal_func) (void *signal_arg, int value); 14 void (*signal_func) (void *signal_arg, int value);
15 void *signal_arg; 15 void *signal_arg;
16 ev_async async_w; 16 ev_async async_w;
17 thread_t tid; 17 thread_t tid;
18 unsigned int max_loops;
19 unsigned int count;
18 20
19 cond_t invoke_cv; 21 cond_t invoke_cv;
20 22
21 SV *interrupt; 23 SV *interrupt;
22} udat; 24} udat;
23 25
26static void loop_set_cb (EV_P);
27
28static void
29fg_invoke_pending (EV_P)
30{
31 udat *u = ev_userdata (EV_A);
32
33 u->count = ev_pending_count (EV_A);
34
35 if (u->count)
36 ev_invoke_pending (EV_A);
37}
38
24static void 39static void
25c_func (pTHX_ void *loop_, int value) 40c_func (pTHX_ void *loop_, int value)
26{ 41{
27 struct ev_loop *loop = (struct ev_loop *)loop_; 42 struct ev_loop *loop = (struct ev_loop *)loop_;
28 udat *u = ev_userdata (EV_A); 43 udat *u = ev_userdata (EV_A);
44 int i;
45
29 X_LOCK (u->lock); 46 X_LOCK (u->lock);
30 ev_invoke_pending (loop); 47 ev_invoke_pending (EV_A);
48
49 /* do any additional foreground loop runs */
50 for (i = u->max_loops; i--; )
51 {
52 /* this is a bit tricky, but we can manage... */
53 u->count = 0;
54
55 ev_set_invoke_pending_cb (EV_A, fg_invoke_pending);
56 ev_set_loop_release_cb (EV_A, 0, 0);
57 ev_loop (EV_A, EVLOOP_NONBLOCK);
58 loop_set_cb (EV_A);
59
60 if (!u->count)
61 break;
62 }
63
31 X_COND_SIGNAL (u->invoke_cv); 64 X_COND_SIGNAL (u->invoke_cv);
32 X_UNLOCK (u->lock); 65 X_UNLOCK (u->lock);
33} 66}
34 67
35static void 68static void
54 87
55static void 88static void
56l_invoke (EV_P) 89l_invoke (EV_P)
57{ 90{
58 udat *u = ev_userdata (EV_A); 91 udat *u = ev_userdata (EV_A);
92
93 while (ev_pending_count (EV_A))
94 {
59 u->signal_func (u->signal_arg, 1); 95 u->signal_func (u->signal_arg, 1);
60 X_COND_WAIT (u->invoke_cv, u->lock); 96 X_COND_WAIT (u->invoke_cv, u->lock);
97 }
98}
99
100static void
101loop_set_cb (EV_P)
102{
103 ev_set_invoke_pending_cb (EV_A, l_invoke);
104 ev_set_loop_release_cb (EV_A, l_release, l_acquire);
61} 105}
62 106
63X_THREAD_PROC(l_run) 107X_THREAD_PROC(l_run)
64{ 108{
65 struct ev_loop *loop = (struct ev_loop *)thr_arg; 109 struct ev_loop *loop = (struct ev_loop *)thr_arg;
80 124
81static void 125static void
82scope_lock_cb (pTHX_ void *loop_) 126scope_lock_cb (pTHX_ void *loop_)
83{ 127{
84 struct ev_loop *loop = (struct ev_loop *)SvIVX ((SV *)loop_); 128 struct ev_loop *loop = (struct ev_loop *)SvIVX ((SV *)loop_);
85 udat *u = ev_userdata (loop); 129 udat *u = ev_userdata (EV_A);
86 130
87 X_UNLOCK (u->lock); 131 X_UNLOCK (u->lock);
88 SvREFCNT_dec ((SV *)loop_); 132 SvREFCNT_dec ((SV *)loop_);
89} 133}
90 134
117 u->interrupt = newSVsv (interrupt); 161 u->interrupt = newSVsv (interrupt);
118 u->signal_func = (void (*)(void *, int))sig_func; 162 u->signal_func = (void (*)(void *, int))sig_func;
119 u->signal_arg = sig_arg; 163 u->signal_arg = sig_arg;
120 164
121 ev_async_init (&u->async_w, async_cb); 165 ev_async_init (&u->async_w, async_cb);
122 ev_async_start (loop, &u->async_w); 166 ev_async_start (EV_A, &u->async_w);
123 167
124 pthread_mutexattr_init (&ma); 168 pthread_mutexattr_init (&ma);
125 pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE); 169 pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE);
126 pthread_mutex_init (&u->lock, &ma); 170 pthread_mutex_init (&u->lock, &ma);
127 pthread_mutexattr_destroy (&ma); 171 pthread_mutexattr_destroy (&ma);
128 172
129 pthread_cond_init (&u->invoke_cv, 0); 173 pthread_cond_init (&u->invoke_cv, 0);
130 174
131 ev_set_userdata (loop, u); 175 ev_set_userdata (EV_A, u);
132 ev_set_invoke_pending_cb (loop, l_invoke); 176 loop_set_cb (EV_A);
133 ev_set_loop_release_cb (loop, l_release, l_acquire);
134 177
135 thread_create (&u->tid, l_run, loop); 178 thread_create (&u->tid, l_run, loop);
136} 179}
137 180
138SV * 181SV *
139interrupt (SV *loop_) 182interrupt (SV *loop_)
140 CODE: 183 CODE:
141{ 184{
142 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); 185 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
143 udat *u = ev_userdata (loop); 186 udat *u = ev_userdata (EV_A);
144 187
145 RETVAL = newSVsv (u->interrupt); 188 RETVAL = newSVsv (u->interrupt);
146} 189}
147 OUTPUT: 190 OUTPUT:
148 RETVAL 191 RETVAL
192
193void
194set_max_foreground_loops (SV *loop_, UV max_loops)
195 CODE:
196{
197 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
198 udat *u = ev_userdata (EV_A);
199
200 u->max_loops = max_loops;
201}
149 202
150void 203void
151lock (SV *loop_) 204lock (SV *loop_)
152 ALIAS: 205 ALIAS:
153 lock = 0 206 lock = 0
154 unlock = 1 207 unlock = 1
155 notify = 2 208 notify = 2
156 CODE: 209 CODE:
157{ 210{
158 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); 211 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
159 udat *u = ev_userdata (loop); 212 udat *u = ev_userdata (EV_A);
160 213
161 switch (ix) 214 switch (ix)
162 { 215 {
163 case 0: X_LOCK (u->lock); break; 216 case 0: X_LOCK (u->lock); break;
164 case 1: X_UNLOCK (u->lock); break; 217 case 1: X_UNLOCK (u->lock); break;
165 case 2: ev_async_send (loop, &u->async_w); break; 218 case 2: ev_async_send (EV_A, &u->async_w); break;
166 } 219 }
167} 220}
168 221
169void 222void
170scope_lock (SV *loop_) 223scope_lock (SV *loop_)
171 CODE: 224 CODE:
172{ 225{
173 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); 226 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
174 udat *u = ev_userdata (loop); 227 udat *u = ev_userdata (EV_A);
175 228
176 X_LOCK (u->lock); 229 X_LOCK (u->lock);
177 230
178 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */ 231 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
179 SAVEDESTRUCTOR_X (scope_lock_cb, (void *)SvREFCNT_inc (SvRV (loop_))); 232 SAVEDESTRUCTOR_X (scope_lock_cb, (void *)SvREFCNT_inc (SvRV (loop_)));
183void 236void
184DESTROY (SV *loop_) 237DESTROY (SV *loop_)
185 CODE: 238 CODE:
186{ 239{
187 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); 240 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
188 udat *u = ev_userdata (loop); 241 udat *u = ev_userdata (EV_A);
189 242
190 if (u) 243 if (u)
191 { 244 {
192 X_LOCK (u->lock); 245 X_LOCK (u->lock);
193 ev_async_stop (loop, &u->async_w); 246 ev_async_stop (EV_A, &u->async_w);
194 /* now thread is around blocking call, or in pthread_cond_wait */ 247 /* now thread is around blocking call, or in pthread_cond_wait */
195 pthread_cancel (u->tid); 248 pthread_cancel (u->tid);
196 pthread_mutex_destroy (&u->lock); 249 pthread_mutex_destroy (&u->lock);
197 pthread_cond_destroy (&u->invoke_cv); 250 pthread_cond_destroy (&u->invoke_cv);
198 SvREFCNT_dec (u->interrupt); 251 SvREFCNT_dec (u->interrupt);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines