Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2006 Lennart Poettering
5 : :
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
8 : : published by the Free Software Foundation; either version 2.1 of the
9 : : License, or (at your option) any later version.
10 : :
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 : : Lesser General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU Lesser General Public
17 : : License along with PulseAudio; if not, write to the Free Software
18 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 : : USA.
20 : : ***/
21 : :
22 : : #ifdef HAVE_CONFIG_H
23 : : #include <config.h>
24 : : #endif
25 : :
26 : : #include <unistd.h>
27 : : #include <errno.h>
28 : :
29 : : #include <pulsecore/thread.h>
30 : : #include <pulsecore/semaphore.h>
31 : : #include <pulsecore/macro.h>
32 : :
33 : : #include "thread-mq.h"
34 : :
35 : 0 : PA_STATIC_TLS_DECLARE_NO_FREE(thread_mq);
36 : :
37 : 0 : static void asyncmsgq_read_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
38 : 0 : pa_thread_mq *q = userdata;
39 : : pa_asyncmsgq *aq;
40 : :
41 [ # # ]: 0 : pa_assert(pa_asyncmsgq_read_fd(q->outq) == fd);
42 [ # # ]: 0 : pa_assert(events == PA_IO_EVENT_INPUT);
43 : :
44 : 0 : pa_asyncmsgq_ref(aq = q->outq);
45 : 0 : pa_asyncmsgq_read_after_poll(aq);
46 : :
47 : : for (;;) {
48 : : pa_msgobject *object;
49 : : int code;
50 : : void *data;
51 : : int64_t offset;
52 : : pa_memchunk chunk;
53 : :
54 : : /* Check whether there is a message for us to process */
55 [ # # ]: 0 : while (pa_asyncmsgq_get(aq, &object, &code, &data, &offset, &chunk, 0) >= 0) {
56 : : int ret;
57 : :
58 : 0 : ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
59 : 0 : pa_asyncmsgq_done(aq, ret);
60 : : }
61 : :
62 [ # # ]: 0 : if (pa_asyncmsgq_read_before_poll(aq) == 0)
63 : : break;
64 : : }
65 : :
66 : 0 : pa_asyncmsgq_unref(aq);
67 : 0 : }
68 : :
69 : 0 : static void asyncmsgq_write_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
70 : 0 : pa_thread_mq *q = userdata;
71 : :
72 [ # # ]: 0 : pa_assert(pa_asyncmsgq_write_fd(q->inq) == fd);
73 [ # # ]: 0 : pa_assert(events == PA_IO_EVENT_INPUT);
74 : :
75 : 0 : pa_asyncmsgq_write_after_poll(q->inq);
76 : 0 : pa_asyncmsgq_write_before_poll(q->inq);
77 : 0 : }
78 : :
79 : 0 : void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop, pa_rtpoll *rtpoll) {
80 [ # # ]: 0 : pa_assert(q);
81 [ # # ]: 0 : pa_assert(mainloop);
82 : :
83 : 0 : q->mainloop = mainloop;
84 [ # # ]: 0 : pa_assert_se(q->inq = pa_asyncmsgq_new(0));
85 [ # # ]: 0 : pa_assert_se(q->outq = pa_asyncmsgq_new(0));
86 : :
87 [ # # ]: 0 : pa_assert_se(pa_asyncmsgq_read_before_poll(q->outq) == 0);
88 [ # # ]: 0 : pa_assert_se(q->read_event = mainloop->io_new(mainloop, pa_asyncmsgq_read_fd(q->outq), PA_IO_EVENT_INPUT, asyncmsgq_read_cb, q));
89 : :
90 : 0 : pa_asyncmsgq_write_before_poll(q->inq);
91 [ # # ]: 0 : pa_assert_se(q->write_event = mainloop->io_new(mainloop, pa_asyncmsgq_write_fd(q->inq), PA_IO_EVENT_INPUT, asyncmsgq_write_cb, q));
92 : :
93 : 0 : pa_rtpoll_item_new_asyncmsgq_read(rtpoll, PA_RTPOLL_EARLY, q->inq);
94 : 0 : pa_rtpoll_item_new_asyncmsgq_write(rtpoll, PA_RTPOLL_LATE, q->outq);
95 : 0 : }
96 : :
97 : 0 : void pa_thread_mq_done(pa_thread_mq *q) {
98 [ # # ]: 0 : pa_assert(q);
99 : :
100 : : /* Since we are called from main context we can be sure that the
101 : : * inq is empty. However, the outq might still contain messages
102 : : * for the main loop, which we need to dispatch (e.g. release
103 : : * msgs, other stuff). Hence do so if we aren't currently
104 : : * dispatching anyway. */
105 : :
106 [ # # ]: 0 : if (!pa_asyncmsgq_dispatching(q->outq))
107 : 0 : pa_asyncmsgq_flush(q->outq, TRUE);
108 : :
109 : 0 : q->mainloop->io_free(q->read_event);
110 : 0 : q->mainloop->io_free(q->write_event);
111 : 0 : q->read_event = q->write_event = NULL;
112 : :
113 : 0 : pa_asyncmsgq_unref(q->inq);
114 : 0 : pa_asyncmsgq_unref(q->outq);
115 : 0 : q->inq = q->outq = NULL;
116 : :
117 : 0 : q->mainloop = NULL;
118 : 0 : }
119 : :
120 : 0 : void pa_thread_mq_install(pa_thread_mq *q) {
121 [ # # ]: 0 : pa_assert(q);
122 : :
123 [ # # ]: 0 : pa_assert(!(PA_STATIC_TLS_GET(thread_mq)));
124 : : PA_STATIC_TLS_SET(thread_mq, q);
125 : 0 : }
126 : :
127 : 0 : pa_thread_mq *pa_thread_mq_get(void) {
128 : 0 : return PA_STATIC_TLS_GET(thread_mq);
129 : : }
|