]>
code.delx.au - pulseaudio/blob - src/pulse/thread-mainloop.c
4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #ifdef HAVE_SYS_POLL_H
33 #include "../pulsecore/poll.h"
36 #include <pulse/xmalloc.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/hashmap.h>
40 #include <pulsecore/thread.h>
41 #include <pulsecore/mutex.h>
44 #include "thread-mainloop.h"
46 struct pa_threaded_mainloop
{
47 pa_mainloop
*real_mainloop
;
52 pa_cond
* cond
, *accept_cond
;
55 static inline int in_worker(pa_threaded_mainloop
*m
) {
56 return pa_thread_self() == m
->thread
;
59 static int poll_func(struct pollfd
*ufds
, unsigned long nfds
, int timeout
, void *userdata
) {
60 pa_mutex
*mutex
= userdata
;
65 /* Before entering poll() we unlock the mutex, so that
66 * avahi_simple_poll_quit() can succeed from another thread. */
68 pa_mutex_unlock(mutex
);
69 r
= poll(ufds
, nfds
, timeout
);
75 static void thread(void *userdata
) {
76 pa_threaded_mainloop
*m
= userdata
;
81 /* Make sure that signals are delivered to the main thread */
83 pthread_sigmask(SIG_BLOCK
, &mask
, NULL
);
86 pa_mutex_lock(m
->mutex
);
88 pa_mainloop_run(m
->real_mainloop
, NULL
);
90 pa_mutex_unlock(m
->mutex
);
93 pa_threaded_mainloop
*pa_threaded_mainloop_new(void) {
94 pa_threaded_mainloop
*m
;
96 m
= pa_xnew(pa_threaded_mainloop
, 1);
98 if (!(m
->real_mainloop
= pa_mainloop_new())) {
103 m
->mutex
= pa_mutex_new(1);
104 m
->cond
= pa_cond_new();
105 m
->accept_cond
= pa_cond_new();
108 pa_mainloop_set_poll_func(m
->real_mainloop
, poll_func
, m
->mutex
);
115 void pa_threaded_mainloop_free(pa_threaded_mainloop
* m
) {
118 /* Make sure that this function is not called from the helper thread */
119 assert((m
->thread
&& !pa_thread_is_running(m
->thread
)) || !in_worker(m
));
121 pa_threaded_mainloop_stop(m
);
123 pa_thread_free(m
->thread
);
125 pa_mainloop_free(m
->real_mainloop
);
127 pa_mutex_free(m
->mutex
);
128 pa_cond_free(m
->cond
);
129 pa_cond_free(m
->accept_cond
);
134 int pa_threaded_mainloop_start(pa_threaded_mainloop
*m
) {
137 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
));
139 if (!(m
->thread
= pa_thread_new(thread
, m
)))
145 void pa_threaded_mainloop_stop(pa_threaded_mainloop
*m
) {
148 if (!m
->thread
|| !pa_thread_is_running(m
->thread
))
151 /* Make sure that this function is not called from the helper thread */
152 assert(!in_worker(m
));
154 pa_mutex_lock(m
->mutex
);
155 pa_mainloop_quit(m
->real_mainloop
, 0);
156 pa_mutex_unlock(m
->mutex
);
158 pa_thread_join(m
->thread
);
161 void pa_threaded_mainloop_lock(pa_threaded_mainloop
*m
) {
164 /* Make sure that this function is not called from the helper thread */
165 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
167 pa_mutex_lock(m
->mutex
);
170 void pa_threaded_mainloop_unlock(pa_threaded_mainloop
*m
) {
173 /* Make sure that this function is not called from the helper thread */
174 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
176 pa_mutex_unlock(m
->mutex
);
179 void pa_threaded_mainloop_signal(pa_threaded_mainloop
*m
, int wait_for_accept
) {
182 pa_cond_signal(m
->cond
, 1);
184 if (wait_for_accept
&& m
->n_waiting
> 0)
185 pa_cond_wait(m
->accept_cond
, m
->mutex
);
188 void pa_threaded_mainloop_wait(pa_threaded_mainloop
*m
) {
191 /* Make sure that this function is not called from the helper thread */
192 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
196 pa_cond_wait(m
->cond
, m
->mutex
);
198 assert(m
->n_waiting
> 0);
202 void pa_threaded_mainloop_accept(pa_threaded_mainloop
*m
) {
205 /* Make sure that this function is not called from the helper thread */
206 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
208 pa_cond_signal(m
->accept_cond
, 0);
211 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop
*m
) {
214 return pa_mainloop_get_retval(m
->real_mainloop
);
217 pa_mainloop_api
* pa_threaded_mainloop_get_api(pa_threaded_mainloop
*m
) {
220 return pa_mainloop_get_api(m
->real_mainloop
);