]>
code.delx.au - pulseaudio/blob - src/polyp/thread-mainloop.c
62813acd3a3199ce36526d10c05c3fc640accb02
4 This file is part of polypaudio.
6 polypaudio 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 polypaudio 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 polypaudio; 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 "../polypcore/poll.h"
40 #include <polypcore/xmalloc.h>
43 #include "thread-mainloop.h"
47 struct pa_threaded_mainloop
{
48 pa_mainloop
*real_mainloop
;
50 pthread_mutex_t mutex
;
52 pthread_cond_t cond
, release_cond
;
56 static int poll_func(struct pollfd
*ufds
, unsigned long nfds
, int timeout
, void *userdata
) {
57 pthread_mutex_t
*mutex
= userdata
;
62 /* Before entering poll() we unlock the mutex, so that
63 * avahi_simple_poll_quit() can succeed from another thread. */
65 pthread_mutex_unlock(mutex
);
66 r
= poll(ufds
, nfds
, timeout
);
67 pthread_mutex_lock(mutex
);
72 static void* thread(void *userdata
){
73 pa_threaded_mainloop
*m
= userdata
;
76 /* Make sure that signals are delivered to the main thread */
78 pthread_sigmask(SIG_BLOCK
, &mask
, NULL
);
80 pthread_mutex_lock(&m
->mutex
);
81 pa_mainloop_run(m
->real_mainloop
, NULL
);
82 pthread_mutex_unlock(&m
->mutex
);
87 pa_threaded_mainloop
*pa_threaded_mainloop_new(void) {
88 pa_threaded_mainloop
*m
;
89 pthread_mutexattr_t a
;
91 m
= pa_xnew(pa_threaded_mainloop
, 1);
93 if (!(m
->real_mainloop
= pa_mainloop_new())) {
98 pa_mainloop_set_poll_func(m
->real_mainloop
, poll_func
, &m
->mutex
);
100 pthread_mutexattr_init(&a
);
101 pthread_mutexattr_settype(&a
, PTHREAD_MUTEX_RECURSIVE
);
102 pthread_mutex_init(&m
->mutex
, &a
);
103 pthread_mutexattr_destroy(&a
);
105 pthread_cond_init(&m
->cond
, NULL
);
106 pthread_cond_init(&m
->release_cond
, NULL
);
107 m
->thread_running
= 0;
113 void pa_threaded_mainloop_free(pa_threaded_mainloop
* m
) {
116 /* Make sure that this function is not called from the helper thread */
117 assert(!m
->thread_running
|| !pthread_equal(pthread_self(), m
->thread_id
));
119 if (m
->thread_running
)
120 pa_threaded_mainloop_stop(m
);
122 if (m
->real_mainloop
)
123 pa_mainloop_free(m
->real_mainloop
);
125 pthread_mutex_destroy(&m
->mutex
);
126 pthread_cond_destroy(&m
->cond
);
127 pthread_cond_destroy(&m
->release_cond
);
132 int pa_threaded_mainloop_start(pa_threaded_mainloop
*m
) {
135 assert(!m
->thread_running
);
137 pthread_mutex_lock(&m
->mutex
);
139 if (pthread_create(&m
->thread_id
, NULL
, thread
, m
) < 0) {
140 pthread_mutex_unlock(&m
->mutex
);
144 m
->thread_running
= 1;
146 pthread_mutex_unlock(&m
->mutex
);
151 void pa_threaded_mainloop_stop(pa_threaded_mainloop
*m
) {
154 if (!m
->thread_running
)
157 /* Make sure that this function is not called from the helper thread */
158 assert(!pthread_equal(pthread_self(), m
->thread_id
));
160 pthread_mutex_lock(&m
->mutex
);
161 pa_mainloop_quit(m
->real_mainloop
, 0);
162 pthread_mutex_unlock(&m
->mutex
);
164 pthread_join(m
->thread_id
, NULL
);
165 m
->thread_running
= 0;
170 void pa_threaded_mainloop_lock(pa_threaded_mainloop
*m
) {
173 /* Make sure that this function is not called from the helper thread */
174 assert(!m
->thread_running
|| !pthread_equal(pthread_self(), m
->thread_id
));
176 pthread_mutex_lock(&m
->mutex
);
179 void pa_threaded_mainloop_unlock(pa_threaded_mainloop
*m
) {
182 /* Make sure that this function is not called from the helper thread */
183 assert(!m
->thread_running
|| !pthread_equal(pthread_self(), m
->thread_id
));
185 pthread_mutex_unlock(&m
->mutex
);
188 void pa_threaded_mainloop_signal(pa_threaded_mainloop
*m
, int wait_for_release
) {
191 pthread_cond_broadcast(&m
->cond
);
193 if (wait_for_release
&& m
->n_waiting
> 0)
194 pthread_cond_wait(&m
->release_cond
, &m
->mutex
);
197 void pa_threaded_mainloop_wait(pa_threaded_mainloop
*m
) {
200 /* Make sure that this function is not called from the helper thread */
201 assert(!m
->thread_running
|| !pthread_equal(pthread_self(), m
->thread_id
));
204 pthread_cond_wait(&m
->cond
, &m
->mutex
);
205 assert(m
->n_waiting
> 0);
207 pthread_cond_signal(&m
->release_cond
);
210 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop
*m
) {
213 return pa_mainloop_get_retval(m
->real_mainloop
);
216 pa_mainloop_api
* pa_threaded_mainloop_get_api(pa_threaded_mainloop
*m
) {
219 return pa_mainloop_get_api(m
->real_mainloop
);
222 #else /* OS_IS_WIN32 */
224 // FIXME: Use Win32 primitives
226 #endif /* OS_IS_WIN32 */