… | |
… | |
14 | void *signal_arg; |
14 | void *signal_arg; |
15 | ev_async async_w; |
15 | ev_async async_w; |
16 | thread_t tid; |
16 | thread_t tid; |
17 | |
17 | |
18 | cond_t invoke_cv; |
18 | cond_t invoke_cv; |
19 | mutex_t invoke_mutex; |
|
|
20 | |
19 | |
21 | SV *interrupt; |
20 | SV *interrupt; |
22 | } udat; |
21 | } udat; |
23 | |
22 | |
24 | static void |
23 | static void |
… | |
… | |
26 | { |
25 | { |
27 | struct ev_loop *loop = (struct ev_loop *)loop_; |
26 | struct ev_loop *loop = (struct ev_loop *)loop_; |
28 | udat *u = ev_userdata (EV_A); |
27 | udat *u = ev_userdata (EV_A); |
29 | X_LOCK (u->lock); |
28 | X_LOCK (u->lock); |
30 | ev_invoke_pending (loop); |
29 | ev_invoke_pending (loop); |
31 | X_UNLOCK (u->lock); |
|
|
32 | X_COND_SIGNAL (u->invoke_cv); |
30 | X_COND_SIGNAL (u->invoke_cv); |
|
|
31 | X_UNLOCK (u->lock); |
33 | } |
32 | } |
34 | |
33 | |
35 | static void |
34 | static void |
36 | async_cb (EV_P_ ev_async *w, int revents) |
35 | async_cb (EV_P_ ev_async *w, int revents) |
37 | { |
36 | { |
… | |
… | |
54 | |
53 | |
55 | static void |
54 | static void |
56 | l_invoke (EV_P) |
55 | l_invoke (EV_P) |
57 | { |
56 | { |
58 | udat *u = ev_userdata (EV_A); |
57 | udat *u = ev_userdata (EV_A); |
59 | X_UNLOCK (u->lock); |
|
|
60 | u->signal_func (u->signal_arg, 1); |
58 | u->signal_func (u->signal_arg, 1); |
61 | X_COND_WAIT (u->invoke_cv, u->invoke_mutex); |
59 | X_COND_WAIT (u->invoke_cv, u->lock); |
62 | X_LOCK (u->lock); |
|
|
63 | } |
60 | } |
64 | |
61 | |
65 | X_THREAD_PROC(l_run) |
62 | X_THREAD_PROC(l_run) |
66 | { |
63 | { |
67 | struct ev_loop *loop = (struct ev_loop *)thr_arg; |
64 | struct ev_loop *loop = (struct ev_loop *)thr_arg; |
68 | udat *u = ev_userdata (loop); |
65 | udat *u = ev_userdata (loop); |
69 | |
66 | |
70 | X_LOCK (u->invoke_mutex); |
|
|
71 | X_LOCK (u->lock); |
67 | X_LOCK (u->lock); |
72 | ev_ref (loop); /* really? */ |
68 | /* yeah */ |
73 | for (;;) /* really? */ |
69 | pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); |
|
|
70 | |
|
|
71 | ev_ref (loop); |
74 | ev_loop (loop, 0); |
72 | ev_loop (loop, 0); |
|
|
73 | ev_unref (loop); |
|
|
74 | |
75 | X_UNLOCK (u->lock); |
75 | X_UNLOCK (u->lock); |
|
|
76 | |
|
|
77 | return 0; |
76 | } |
78 | } |
77 | |
79 | |
78 | static void |
80 | static void |
79 | scope_lock_cb (pTHX_ void *loop_) |
81 | scope_lock_cb (pTHX_ void *loop_) |
80 | { |
82 | { |
… | |
… | |
119 | ev_async_start (loop, &u->async_w); |
121 | ev_async_start (loop, &u->async_w); |
120 | |
122 | |
121 | pthread_mutexattr_init (&ma); |
123 | pthread_mutexattr_init (&ma); |
122 | pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE); |
124 | pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE); |
123 | pthread_mutex_init (&u->lock, &ma); |
125 | pthread_mutex_init (&u->lock, &ma); |
124 | pthread_mutex_init (&u->invoke_mutex, &ma); |
|
|
125 | pthread_mutexattr_destroy (&ma); |
126 | pthread_mutexattr_destroy (&ma); |
126 | |
127 | |
127 | pthread_cond_init (&u->invoke_cv, 0); |
128 | pthread_cond_init (&u->invoke_cv, 0); |
128 | |
129 | |
129 | ev_set_userdata (loop, u); |
130 | ev_set_userdata (loop, u); |
130 | ev_set_invoke_pending_cb (loop, l_invoke); |
131 | ev_set_invoke_pending_cb (loop, l_invoke); |
131 | ev_set_loop_release_cb (loop, l_release, l_acquire); |
132 | ev_set_loop_release_cb (loop, l_release, l_acquire); |
132 | |
133 | |
133 | pthread_create (&u->tid, 0, l_run, loop); |
134 | thread_create (&u->tid, l_run, loop); |
134 | } |
135 | } |
135 | |
136 | |
136 | SV * |
137 | SV * |
137 | interrupt (SV *loop_) |
138 | interrupt (SV *loop_) |
138 | CODE: |
139 | CODE: |
… | |
… | |
185 | struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); |
186 | struct ev_loop *loop = (struct ev_loop *)SvIVX (SvRV (loop_)); |
186 | udat *u = ev_userdata (loop); |
187 | udat *u = ev_userdata (loop); |
187 | |
188 | |
188 | if (u) |
189 | if (u) |
189 | { |
190 | { |
190 | pthread_cancel (u->tid); |
|
|
191 | ev_async_send (loop, &u->async_w); |
|
|
192 | pthread_join (u->tid, 0); |
|
|
193 | X_LOCK (u->lock); |
191 | X_LOCK (u->lock); |
194 | ev_async_stop (loop, &u->async_w); |
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); |
195 | pthread_mutex_destroy (&u->lock); |
196 | pthread_cond_destroy (&u->invoke_cv); |
196 | pthread_cond_destroy (&u->invoke_cv); |
197 | pthread_mutex_destroy (&u->invoke_mutex); /* TODO: locked by another thread... */ |
|
|
198 | SvREFCNT_dec (u->interrupt); |
197 | SvREFCNT_dec (u->interrupt); |
199 | Safefree (u); |
198 | Safefree (u); |
200 | } |
199 | } |
201 | } |
200 | } |
202 | |
201 | |