ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/EV-Loop-Async/Async.xs
Revision: 1.2
Committed: Tue Jul 14 13:24:34 2009 UTC (15 years ago) by root
Branch: MAIN
Changes since 1.1: +40 -7 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 mutex_t invoke_mutex;
20
21 SV *interrupt;
22 } udat;
23
24 static void
25 c_func (pTHX_ void *loop_, int value)
26 {
27 struct ev_loop *loop = (struct ev_loop *)loop_;
28 udat *u = ev_userdata (EV_A);
29 X_LOCK (u->lock);
30 ev_invoke_pending (loop);
31 X_UNLOCK (u->lock);
32 X_COND_SIGNAL (u->invoke_cv);
33 }
34
35 static void
36 async_cb (EV_P_ ev_async *w, int revents)
37 {
38 /* just used for the side effects */
39 }
40
41 static void
42 l_release (EV_P)
43 {
44 udat *u = ev_userdata (EV_A);
45 X_UNLOCK (u->lock);
46 }
47
48 static void
49 l_acquire (EV_P)
50 {
51 udat *u = ev_userdata (EV_A);
52 X_LOCK (u->lock);
53 }
54
55 static void
56 l_invoke (EV_P)
57 {
58 udat *u = ev_userdata (EV_A);
59 X_UNLOCK (u->lock);
60 u->signal_func (u->signal_arg, 1);
61 X_COND_WAIT (u->invoke_cv, u->invoke_mutex);
62 X_LOCK (u->lock);
63 }
64
65 X_THREAD_PROC(l_run)
66 {
67 struct ev_loop *loop = (struct ev_loop *)thr_arg;
68 udat *u = ev_userdata (loop);
69
70 X_LOCK (u->invoke_mutex);
71 X_LOCK (u->lock);
72 ev_ref (loop); /* really? */
73 for (;;) /* really? */
74 ev_loop (loop, 0);
75 X_UNLOCK (u->lock);
76 }
77
78 static void
79 scope_lock_cb (pTHX_ void *loop_)
80 {
81 struct ev_loop *loop = (struct ev_loop *)SvIVX ((SV *)loop_);
82 udat *u = ev_userdata (loop);
83
84 X_UNLOCK (u->lock);
85 SvREFCNT_dec ((SV *)loop_);
86 }
87
88 MODULE = EV::Loop::Async PACKAGE = EV::Loop::Async
89
90 PROTOTYPES: ENABLE
91
92 BOOT:
93 {
94 I_EV_API ("EV::Loop::Async");
95 }
96
97 void
98 _c_func (SV *loop)
99 PPCODE:
100 EXTEND (SP, 2);
101 PUSHs (sv_2mortal (newSViv (PTR2IV (c_func))));
102 PUSHs (sv_2mortal (newSViv (SvIVX (SvRV (loop)))));
103
104 void
105 _attach (SV *loop_, SV *interrupt, IV sig_func, void *sig_arg)
106 CODE:
107 {
108 pthread_mutexattr_t ma;
109 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
110 udat *u;
111
112 Newz (0, u, 1, udat);
113 u->interrupt = newSVsv (interrupt);
114 u->signal_func = (void (*)(void *, int))sig_func;
115 u->signal_arg = sig_arg;
116
117 ev_async_init (&u->async_w, async_cb);
118 ev_async_start (loop, &u->async_w);
119
120 pthread_mutexattr_init (&ma);
121 pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE);
122 pthread_mutex_init (&u->lock, &ma);
123 pthread_mutex_init (&u->invoke_mutex, &ma);
124 pthread_mutexattr_destroy (&ma);
125
126 pthread_cond_init (&u->invoke_cv, 0);
127
128 ev_set_userdata (loop, u);
129 ev_set_invoke_pending_cb (loop, l_invoke);
130 ev_set_loop_release_cb (loop, l_release, l_acquire);
131
132 thread_create (&u->tid, l_run, (void *)loop);
133 }
134
135 SV *
136 interrupt (SV *loop_)
137 CODE:
138 {
139 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
140 udat *u = ev_userdata (loop);
141
142 RETVAL = newSVsv (u->interrupt);
143 }
144 OUTPUT:
145 RETVAL
146
147 void
148 lock (SV *loop_)
149 ALIAS:
150 lock = 0
151 unlock = 1
152 poke = 2
153 CODE:
154 {
155 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
156 udat *u = ev_userdata (loop);
157
158 switch (ix)
159 {
160 case 0: X_LOCK (u->lock); break;
161 case 1: X_UNLOCK (u->lock); break;
162 case 2: ev_async_send (loop, &u->async_w); break;
163 }
164 }
165
166 void
167 scope_lock (SV *loop_)
168 CODE:
169 {
170 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
171 udat *u = ev_userdata (loop);
172
173 X_LOCK (u->lock);
174
175 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
176 SAVEDESTRUCTOR_X (scope_lock_cb, (void *)SvREFCNT_inc (SvRV (loop_)));
177 ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
178 }
179
180 void
181 DESTROY (SV *loop_)
182 CODE:
183 {
184 struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_));
185 udat *u = ev_userdata (loop);
186
187 if (u)
188 {
189 X_LOCK (u->lock);
190 ev_async_send (loop, &u->async_w);
191 pthread_cancel (u->tid);
192 ev_async_stop (loop, &u->async_w);
193 pthread_mutex_destroy (&u->lock);
194 pthread_cond_destroy (&u->invoke_cv);
195 pthread_mutex_destroy (&u->invoke_mutex);
196 Safefree (u);
197 SvREFCNT_dec (u->interrupt);
198 }
199 }
200
201
202