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

# 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     mutex_t invoke_mutex;
20    
21 root 1.2 SV *interrupt;
22 root 1.1 } 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 root 1.2 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 root 1.1 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 root 1.2 _attach (SV *loop_, SV *interrupt, IV sig_func, void *sig_arg)
106 root 1.1 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 root 1.2 u->interrupt = newSVsv (interrupt);
114 root 1.1 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 root 1.2 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 root 1.1 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 root 1.2 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 root 1.1 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 root 1.2 SvREFCNT_dec (u->interrupt);
198 root 1.1 }
199     }
200    
201    
202