]>
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
);
124 pa_thread_free(m
->thread
);
126 pa_mainloop_free(m
->real_mainloop
);
128 pa_mutex_free(m
->mutex
);
129 pa_cond_free(m
->cond
);
130 pa_cond_free(m
->accept_cond
);
135 int pa_threaded_mainloop_start(pa_threaded_mainloop
*m
) {
138 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
));
140 if (!(m
->thread
= pa_thread_new(thread
, m
)))
146 void pa_threaded_mainloop_stop(pa_threaded_mainloop
*m
) {
149 if (!m
->thread
|| !pa_thread_is_running(m
->thread
))
152 /* Make sure that this function is not called from the helper thread */
153 assert(!in_worker(m
));
155 pa_mutex_lock(m
->mutex
);
156 pa_mainloop_quit(m
->real_mainloop
, 0);
157 pa_mutex_unlock(m
->mutex
);
159 pa_thread_join(m
->thread
);
162 void pa_threaded_mainloop_lock(pa_threaded_mainloop
*m
) {
165 /* Make sure that this function is not called from the helper thread */
166 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
168 pa_mutex_lock(m
->mutex
);
171 void pa_threaded_mainloop_unlock(pa_threaded_mainloop
*m
) {
174 /* Make sure that this function is not called from the helper thread */
175 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
177 pa_mutex_unlock(m
->mutex
);
180 void pa_threaded_mainloop_signal(pa_threaded_mainloop
*m
, int wait_for_accept
) {
183 pa_cond_signal(m
->cond
, 1);
185 if (wait_for_accept
&& m
->n_waiting
> 0)
186 pa_cond_wait(m
->accept_cond
, m
->mutex
);
189 void pa_threaded_mainloop_wait(pa_threaded_mainloop
*m
) {
192 /* Make sure that this function is not called from the helper thread */
193 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
197 pa_cond_wait(m
->cond
, m
->mutex
);
199 assert(m
->n_waiting
> 0);
203 void pa_threaded_mainloop_accept(pa_threaded_mainloop
*m
) {
206 /* Make sure that this function is not called from the helper thread */
207 assert(!m
->thread
|| !pa_thread_is_running(m
->thread
) || !in_worker(m
));
209 pa_cond_signal(m
->accept_cond
, 0);
212 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop
*m
) {
215 return pa_mainloop_get_retval(m
->real_mainloop
);
218 pa_mainloop_api
* pa_threaded_mainloop_get_api(pa_threaded_mainloop
*m
) {
221 return pa_mainloop_get_api(m
->real_mainloop
);