4 This file is part of PulseAudio.
6 Copyright 2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #ifdef HAVE_SYS_POLL_H
36 #include "../pulsecore/poll.h"
39 #include <pulse/xmalloc.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/hashmap.h>
43 #include <pulsecore/thread.h>
44 #include <pulsecore/mutex.h>
47 #include "thread-mainloop.h"
49 struct pa_threaded_mainloop {
50 pa_mainloop *real_mainloop;
55 pa_cond* cond, *accept_cond;
58 static inline int in_worker(pa_threaded_mainloop *m) {
59 return pa_thread_self() == m->thread;
62 static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) {
63 pa_mutex *mutex = userdata;
68 /* Before entering poll() we unlock the mutex, so that
69 * avahi_simple_poll_quit() can succeed from another thread. */
71 pa_mutex_unlock(mutex);
72 r = poll(ufds, nfds, timeout);
78 static void thread(void *userdata) {
79 pa_threaded_mainloop *m = userdata;
84 /* Make sure that signals are delivered to the main thread */
86 pthread_sigmask(SIG_BLOCK, &mask, NULL);
89 pa_mutex_lock(m->mutex);
91 pa_mainloop_run(m->real_mainloop, NULL);
93 pa_mutex_unlock(m->mutex);
96 pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
97 pa_threaded_mainloop *m;
99 m = pa_xnew(pa_threaded_mainloop, 1);
101 if (!(m->real_mainloop = pa_mainloop_new())) {
106 m->mutex = pa_mutex_new(1);
107 m->cond = pa_cond_new();
108 m->accept_cond = pa_cond_new();
111 pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex);
118 void pa_threaded_mainloop_free(pa_threaded_mainloop* m) {
121 /* Make sure that this function is not called from the helper thread */
122 assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m));
124 pa_threaded_mainloop_stop(m);
127 pa_thread_free(m->thread);
129 pa_mainloop_free(m->real_mainloop);
131 pa_mutex_free(m->mutex);
132 pa_cond_free(m->cond);
133 pa_cond_free(m->accept_cond);
138 int pa_threaded_mainloop_start(pa_threaded_mainloop *m) {
141 assert(!m->thread || !pa_thread_is_running(m->thread));
143 if (!(m->thread = pa_thread_new(thread, m)))
149 void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) {
152 if (!m->thread || !pa_thread_is_running(m->thread))
155 /* Make sure that this function is not called from the helper thread */
156 assert(!in_worker(m));
158 pa_mutex_lock(m->mutex);
159 pa_mainloop_quit(m->real_mainloop, 0);
160 pa_mutex_unlock(m->mutex);
162 pa_thread_join(m->thread);
165 void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) {
168 /* Make sure that this function is not called from the helper thread */
169 assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
171 pa_mutex_lock(m->mutex);
174 void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
177 /* Make sure that this function is not called from the helper thread */
178 assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
180 pa_mutex_unlock(m->mutex);
183 void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
186 pa_cond_signal(m->cond, 1);
188 if (wait_for_accept && m->n_waiting > 0)
189 pa_cond_wait(m->accept_cond, m->mutex);
192 void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
195 /* Make sure that this function is not called from the helper thread */
196 assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
200 pa_cond_wait(m->cond, m->mutex);
202 assert(m->n_waiting > 0);
206 void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
209 /* Make sure that this function is not called from the helper thread */
210 assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
212 pa_cond_signal(m->accept_cond, 0);
215 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) {
218 return pa_mainloop_get_retval(m->real_mainloop);
221 pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) {
224 return pa_mainloop_get_api(m->real_mainloop);