]>
code.delx.au - pulseaudio/blob - src/pulse/thread-mainloop.c
2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <pulsecore/poll.h>
36 #include <pulse/xmalloc.h>
37 #include <pulse/mainloop.h>
38 #include <pulse/i18n.h>
40 #include <pulsecore/log.h>
41 #include <pulsecore/hashmap.h>
42 #include <pulsecore/thread.h>
43 #include <pulsecore/mutex.h>
44 #include <pulsecore/macro.h>
46 #include "thread-mainloop.h"
48 struct pa_threaded_mainloop
{
49 pa_mainloop
*real_mainloop
;
54 pa_cond
* cond
, *accept_cond
;
57 static inline int in_worker(pa_threaded_mainloop
*m
) {
58 return pa_thread_self() == m
->thread
;
61 static int poll_func(struct pollfd
*ufds
, unsigned long nfds
, int timeout
, void *userdata
) {
62 pa_mutex
*mutex
= userdata
;
67 /* Before entering poll() we unlock the mutex, so that
68 * avahi_simple_poll_quit() can succeed from another thread. */
70 pa_mutex_unlock(mutex
);
71 r
= poll(ufds
, nfds
, timeout
);
77 static void thread(void *userdata
) {
78 pa_threaded_mainloop
*m
= userdata
;
83 /* Make sure that signals are delivered to the main thread */
85 pthread_sigmask(SIG_BLOCK
, &mask
, NULL
);
88 pa_mutex_lock(m
->mutex
);
90 pa_mainloop_run(m
->real_mainloop
, NULL
);
92 pa_mutex_unlock(m
->mutex
);
95 pa_threaded_mainloop
*pa_threaded_mainloop_new(void) {
96 pa_threaded_mainloop
*m
;
100 m
= pa_xnew(pa_threaded_mainloop
, 1);
102 if (!(m
->real_mainloop
= pa_mainloop_new())) {
107 m
->mutex
= pa_mutex_new(TRUE
, TRUE
);
108 m
->cond
= pa_cond_new();
109 m
->accept_cond
= pa_cond_new();
112 pa_mainloop_set_poll_func(m
->real_mainloop
, poll_func
, m
->mutex
);
119 void pa_threaded_mainloop_free(pa_threaded_mainloop
* m
) {
122 /* Make sure that this function is not called from the helper thread */
123 pa_assert((m
->thread
&& !pa_thread_is_running(m
->thread
)) || !in_worker(m
));
125 pa_threaded_mainloop_stop(m
);
128 pa_thread_free(m
->thread
);
130 pa_mainloop_free(m
->real_mainloop
);
132 pa_mutex_free(m
->mutex
);
133 pa_cond_free(m
->cond
);
134 pa_cond_free(m
->accept_cond
);
139 int pa_threaded_mainloop_start(pa_threaded_mainloop
*m
) {
142 pa_assert(!m
->thread
|| !pa_thread_is_running(m
->thread
));
144 if (!(m
->thread
= pa_thread_new(thread
, m
)))
150 void pa_threaded_mainloop_stop(pa_threaded_mainloop
*m
) {
153 if (!m
->thread
|| !pa_thread_is_running(m
->thread
))
156 /* Make sure that this function is not called from the helper thread */
157 pa_assert(!in_worker(m
));
159 pa_mutex_lock(m
->mutex
);
160 pa_mainloop_quit(m
->real_mainloop
, 0);
161 pa_mutex_unlock(m
->mutex
);
163 pa_thread_join(m
->thread
);
166 void pa_threaded_mainloop_lock(pa_threaded_mainloop
*m
) {
169 /* Make sure that this function is not called from the helper thread */
170 pa_assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
172 pa_mutex_lock(m
->mutex
);
175 void pa_threaded_mainloop_unlock(pa_threaded_mainloop
*m
) {
178 /* Make sure that this function is not called from the helper thread */
179 pa_assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
181 pa_mutex_unlock(m
->mutex
);
184 void pa_threaded_mainloop_signal(pa_threaded_mainloop
*m
, int wait_for_accept
) {
187 pa_cond_signal(m
->cond
, 1);
189 if (wait_for_accept
&& m
->n_waiting
> 0)
190 pa_cond_wait(m
->accept_cond
, m
->mutex
);
193 void pa_threaded_mainloop_wait(pa_threaded_mainloop
*m
) {
196 /* Make sure that this function is not called from the helper thread */
197 pa_assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
201 pa_cond_wait(m
->cond
, m
->mutex
);
203 pa_assert(m
->n_waiting
> 0);
207 void pa_threaded_mainloop_accept(pa_threaded_mainloop
*m
) {
210 /* Make sure that this function is not called from the helper thread */
211 pa_assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
213 pa_cond_signal(m
->accept_cond
, 0);
216 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop
*m
) {
219 return pa_mainloop_get_retval(m
->real_mainloop
);
222 pa_mainloop_api
* pa_threaded_mainloop_get_api(pa_threaded_mainloop
*m
) {
225 return pa_mainloop_get_api(m
->real_mainloop
);
228 int pa_threaded_mainloop_in_thread(pa_threaded_mainloop
*m
) {
231 return m
->thread
&& pa_thread_self() == m
->thread
;