ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-Loop-Async/Async.xs
Revision: 1.6
Committed: Tue Jul 14 19:05:10 2009 UTC (14 years, 10 months ago) by root
Branch: MAIN
Changes since 1.5: +6 -6 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 root 1.2 SV *interrupt;
21 root 1.1 } 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 root 1.5 X_COND_SIGNAL (u->invoke_cv);
31 root 1.1 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 root 1.5 X_COND_WAIT (u->invoke_cv, u->lock);
60 root 1.1 }
61    
62     X_THREAD_PROC(l_run)
63     {
64     struct ev_loop *loop = (struct ev_loop *)thr_arg;
65    
66 root 1.6 l_acquire (EV_A);
67    
68 root 1.5 /* yeah */
69     pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
70    
71 root 1.6 ev_ref (EV_A);
72     ev_loop (EV_A, 0);
73     ev_unref (EV_A);
74 root 1.5
75 root 1.6 l_release (EV_A);
76 root 1.5
77     return 0;
78 root 1.1 }
79    
80 root 1.2 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 root 1.1 MODULE = EV::Loop::Async PACKAGE = EV::Loop::Async
91    
92     PROTOTYPES: ENABLE
93    
94     BOOT:
95     {
96     I_EV_API ("EV::Loop::Async");
97 root 1.3 CvNODEBUG_on (get_cv ("EV::Loop::Async::scope_lock", 0)); /* otherwise calling scope can be the debugger */
98 root 1.1 }
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 root 1.2 _attach (SV *loop_, SV *interrupt, IV sig_func, void *sig_arg)
109 root 1.1 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 root 1.2 u->interrupt = newSVsv (interrupt);
117 root 1.1 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 root 1.5 thread_create (&u->tid, l_run, loop);
135 root 1.1 }
136    
137 root 1.2 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 root 1.1 void
150     lock (SV *loop_)
151     ALIAS:
152     lock = 0
153     unlock = 1
154 root 1.3 notify = 2
155 root 1.1 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 root 1.2 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 root 1.1 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 root 1.4 X_LOCK (u->lock);
192 root 1.1 ev_async_stop (loop, &u->async_w);
193 root 1.5 /* now thread is around blocking call, or in pthread_cond_wait */
194     pthread_cancel (u->tid);
195 root 1.1 pthread_mutex_destroy (&u->lock);
196     pthread_cond_destroy (&u->invoke_cv);
197 root 1.3 SvREFCNT_dec (u->interrupt);
198 root 1.1 Safefree (u);
199     }
200     }
201    
202    
203