]> code.delx.au - pulseaudio/blob - src/pulse/thread-mainloop.c
add i18n support
[pulseaudio] / src / pulse / thread-mainloop.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <signal.h>
28 #include <stdio.h>
29
30 #ifdef HAVE_POLL_H
31 #include <poll.h>
32 #else
33 #include <pulsecore/poll.h>
34 #endif
35
36 #include <pulse/xmalloc.h>
37 #include <pulse/mainloop.h>
38 #include <pulse/i18n.h>
39
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>
45
46 #include "thread-mainloop.h"
47
48 struct pa_threaded_mainloop {
49 pa_mainloop *real_mainloop;
50 int n_waiting;
51
52 pa_thread* thread;
53 pa_mutex* mutex;
54 pa_cond* cond, *accept_cond;
55 };
56
57 static inline int in_worker(pa_threaded_mainloop *m) {
58 return pa_thread_self() == m->thread;
59 }
60
61 static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) {
62 pa_mutex *mutex = userdata;
63 int r;
64
65 pa_assert(mutex);
66
67 /* Before entering poll() we unlock the mutex, so that
68 * avahi_simple_poll_quit() can succeed from another thread. */
69
70 pa_mutex_unlock(mutex);
71 r = poll(ufds, nfds, timeout);
72 pa_mutex_lock(mutex);
73
74 return r;
75 }
76
77 static void thread(void *userdata) {
78 pa_threaded_mainloop *m = userdata;
79
80 #ifndef OS_IS_WIN32
81 sigset_t mask;
82
83 /* Make sure that signals are delivered to the main thread */
84 sigfillset(&mask);
85 pthread_sigmask(SIG_BLOCK, &mask, NULL);
86 #endif
87
88 pa_mutex_lock(m->mutex);
89
90 pa_mainloop_run(m->real_mainloop, NULL);
91
92 pa_mutex_unlock(m->mutex);
93 }
94
95 pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
96 pa_threaded_mainloop *m;
97
98 pa_init_i18n();
99
100 m = pa_xnew(pa_threaded_mainloop, 1);
101
102 if (!(m->real_mainloop = pa_mainloop_new())) {
103 pa_xfree(m);
104 return NULL;
105 }
106
107 m->mutex = pa_mutex_new(TRUE, TRUE);
108 m->cond = pa_cond_new();
109 m->accept_cond = pa_cond_new();
110 m->thread = NULL;
111
112 pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex);
113
114 m->n_waiting = 0;
115
116 return m;
117 }
118
119 void pa_threaded_mainloop_free(pa_threaded_mainloop* m) {
120 pa_assert(m);
121
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));
124
125 pa_threaded_mainloop_stop(m);
126
127 if (m->thread)
128 pa_thread_free(m->thread);
129
130 pa_mainloop_free(m->real_mainloop);
131
132 pa_mutex_free(m->mutex);
133 pa_cond_free(m->cond);
134 pa_cond_free(m->accept_cond);
135
136 pa_xfree(m);
137 }
138
139 int pa_threaded_mainloop_start(pa_threaded_mainloop *m) {
140 pa_assert(m);
141
142 pa_assert(!m->thread || !pa_thread_is_running(m->thread));
143
144 if (!(m->thread = pa_thread_new(thread, m)))
145 return -1;
146
147 return 0;
148 }
149
150 void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) {
151 pa_assert(m);
152
153 if (!m->thread || !pa_thread_is_running(m->thread))
154 return;
155
156 /* Make sure that this function is not called from the helper thread */
157 pa_assert(!in_worker(m));
158
159 pa_mutex_lock(m->mutex);
160 pa_mainloop_quit(m->real_mainloop, 0);
161 pa_mutex_unlock(m->mutex);
162
163 pa_thread_join(m->thread);
164 }
165
166 void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) {
167 pa_assert(m);
168
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));
171
172 pa_mutex_lock(m->mutex);
173 }
174
175 void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
176 pa_assert(m);
177
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));
180
181 pa_mutex_unlock(m->mutex);
182 }
183
184 void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
185 pa_assert(m);
186
187 pa_cond_signal(m->cond, 1);
188
189 if (wait_for_accept && m->n_waiting > 0)
190 pa_cond_wait(m->accept_cond, m->mutex);
191 }
192
193 void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
194 pa_assert(m);
195
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));
198
199 m->n_waiting ++;
200
201 pa_cond_wait(m->cond, m->mutex);
202
203 pa_assert(m->n_waiting > 0);
204 m->n_waiting --;
205 }
206
207 void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
208 pa_assert(m);
209
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));
212
213 pa_cond_signal(m->accept_cond, 0);
214 }
215
216 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) {
217 pa_assert(m);
218
219 return pa_mainloop_get_retval(m->real_mainloop);
220 }
221
222 pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) {
223 pa_assert(m);
224
225 return pa_mainloop_get_api(m->real_mainloop);
226 }
227
228 int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m) {
229 pa_assert(m);
230
231 return m->thread && pa_thread_self() == m->thread;
232 }