ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/EV-Loop-Async/Async.xs
Revision: 1.5
Committed: Tue Jul 14 18:02:08 2009 UTC (15 years ago) by root
Branch: MAIN
Changes since 1.4: +14 -15 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <stddef.h>
6
7 #include "EVAPI.h"
8 #include "xthread.h"
9
10 /* our userdata */
11 typedef struct {
12 mutex_t lock; /* global loop lock */
13 void (*signal_func) (void *signal_arg, int value);
14 void *signal_arg;
15 ev_async async_w;
16 thread_t tid;
17
18 cond_t invoke_cv;
19
20 SV *interrupt;
21 } udat;
22
23 static void
24 c_func (pTHX_ void *loop_, int value)
25 {
26 struct ev_loop *loop = (struct ev_loop *)loop_;
27 udat *u = ev_userdata (EV_A);
28 X_LOCK (u->lock);
29 ev_invoke_pending (loop);
30 X_COND_SIGNAL (u->invoke_cv);
31 X_UNLOCK (u->lock);
32 }
33
34 static void
35 async_cb (EV_P_ ev_async *w, int revents)
36 {
37 /* just used for the side effects */
38 }
39
40 static void
41 l_release (EV_P)
42 {
43 udat *u = ev_userdata (EV_A);
44 X_UNLOCK (u->lock);
45 }
46
47 static void
48 l_acquire (EV_P)
49 {
50 udat *u = ev_userdata (EV_A);
51 X_LOCK (u->lock);
52 }
53
54 static void
55 l_invoke (EV_P)
56 {
57 udat *u = ev_userdata (EV_A);
58 u->signal_func (u->signal_arg, 1);
59 X_COND_WAIT (u->invoke_cv, u->lock);
60 }
61
62 X_THREAD_PROC(l_run)
63 {
64 struct ev_loop *loop = (struct ev_loop *)thr_arg;
65 udat *u = ev_userdata (loop);
66
67 X_LOCK (u->lock);
68 /* yeah */
69 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
70
71 ev_ref (loop);
72 ev_loop (loop, 0);
73 ev_unref (loop);
74
75 X_UNLOCK (u->lock);
76
77 return 0;
78 }
79
80 static void
81 scope_lock_cb (pTHX_ void *loop_)
82 {
83 struct ev_loop *loop = (struct ev_loop *)SvIVX ((SV *)loop_);
84 udat *u = ev_userdata (loop);
85
86 X_UNLOCK (u->lock);
87 SvREFCNT_dec ((SV *)loop_);
88 }
89
90 MODULE = EV::Loop::Async PACKAGE = EV::Loop::Async
91
92 PROTOTYPES: ENABLE
93
94 BOOT:
95 {
96 I_EV_API ("EV::Loop::Async");
97 CvNODEBUG_on (get_cv ("EV::Loop::Async::scope_lock", 0)); /* otherwise calling scope can be the debugger */
98 }
99
100 void
101 _c_func (SV *loop)
102 PPCODE:
103 EXTEND (SP, 2);
104 PUSHs (sv_2mortal (newSViv (PTR2IV (c_func))));
105 PUSHs (sv_2mortal (newSViv (SvIVX (SvRV (loop)))));
106
107 void
108 _attach (SV *loop_, SV *interrupt, IV sig_func, void *sig_arg)
109 CODE:
110 {
111 pthread_mutexattr_t ma;
112 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
113 udat *u;
114
115 Newz (0, u, 1, udat);
116 u->interrupt = newSVsv (interrupt);
117 u->signal_func = (void (*)(void *, int))sig_func;
118 u->signal_arg = sig_arg;
119
120 ev_async_init (&u->async_w, async_cb);
121 ev_async_start (loop, &u->async_w);
122
123 pthread_mutexattr_init (&ma);
124 pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE);
125 pthread_mutex_init (&u->lock, &ma);
126 pthread_mutexattr_destroy (&ma);
127
128 pthread_cond_init (&u->invoke_cv, 0);
129
130 ev_set_userdata (loop, u);
131 ev_set_invoke_pending_cb (loop, l_invoke);
132 ev_set_loop_release_cb (loop, l_release, l_acquire);
133
134 thread_create (&u->tid, l_run, loop);
135 }
136
137 SV *
138 interrupt (SV *loop_)
139 CODE:
140 {
141 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
142 udat *u = ev_userdata (loop);
143
144 RETVAL = newSVsv (u->interrupt);
145 }
146 OUTPUT:
147 RETVAL
148
149 void
150 lock (SV *loop_)
151 ALIAS:
152 lock = 0
153 unlock = 1
154 notify = 2
155 CODE:
156 {
157 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
158 udat *u = ev_userdata (loop);
159
160 switch (ix)
161 {
162 case 0: X_LOCK (u->lock); break;
163 case 1: X_UNLOCK (u->lock); break;
164 case 2: ev_async_send (loop, &u->async_w); break;
165 }
166 }
167
168 void
169 scope_lock (SV *loop_)
170 CODE:
171 {
172 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
173 udat *u = ev_userdata (loop);
174
175 X_LOCK (u->lock);
176
177 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
178 SAVEDESTRUCTOR_X (scope_lock_cb, (void *)SvREFCNT_inc (SvRV (loop_)));
179 ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
180 }
181
182 void
183 DESTROY (SV *loop_)
184 CODE:
185 {
186 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
187 udat *u = ev_userdata (loop);
188
189 if (u)
190 {
191 X_LOCK (u->lock);
192 ev_async_stop (loop, &u->async_w);
193 /* now thread is around blocking call, or in pthread_cond_wait */
194 pthread_cancel (u->tid);
195 pthread_mutex_destroy (&u->lock);
196 pthread_cond_destroy (&u->invoke_cv);
197 SvREFCNT_dec (u->interrupt);
198 Safefree (u);
199 }
200 }
201
202
203