From 736de36f6822d7ff85bb604ab749af88f8e19e12 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Sep 2006 23:41:20 +0000 Subject: add asynchronous inter-thread notification API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1402 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/anotify.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/anotify.h | 38 +++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 src/pulsecore/anotify.c create mode 100644 src/pulsecore/anotify.h (limited to 'src') diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c new file mode 100644 index 00000000..a61f8442 --- /dev/null +++ b/src/pulsecore/anotify.c @@ -0,0 +1,143 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "anotify.h" + +#define EVENTS_MAX 16 + +struct pa_anotify { + pa_mainloop_api *api; + pa_anotify_cb_t callback; + void *userdata; + int fds[2]; + pa_io_event *io_event; + pa_defer_event *defer_event; + + uint8_t queued_events[EVENTS_MAX]; + unsigned n_queued_events, queue_index; +}; + +static void dispatch_event(pa_anotify *a) { + assert(a); + assert(a->queue_index < a->n_queued_events); + + a->callback(a->queued_events[a->queue_index++], a->userdata); + + if (a->queue_index >= a->n_queued_events) { + a->n_queued_events = 0; + a->queue_index = 0; + + a->api->io_enable(a->io_event, PA_IO_EVENT_INPUT); + a->api->defer_enable(a->defer_event, 0); + } else { + a->api->io_enable(a->io_event, 0); + a->api->defer_enable(a->defer_event, 1); + } +} + +static void io_callback( + pa_mainloop_api *api, + pa_io_event *e, + int fd, + pa_io_event_flags_t events, + void *userdata) { + + pa_anotify *a = userdata; + ssize_t r; + + assert(a); + assert(events == PA_IO_EVENT_INPUT); + assert(a->n_queued_events == 0); + + r = read(fd, a->queued_events, sizeof(a->queued_events)); + assert(r > 0); + + a->n_queued_events = (unsigned) r; + a->queue_index = 0; + + /* Only dispatch a single event */ + dispatch_event(a); +} + +static void defer_callback(pa_mainloop_api *api, pa_defer_event *e, void *userdata) { + pa_anotify *a = userdata; + assert(a); + + dispatch_event(a); +} + +pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) { + pa_anotify *a; + + assert(api); + assert(cb); + + a = pa_xnew(pa_anotify, 1); + + if (pipe(a->fds) < 0) { + pa_xfree(a); + return NULL; + } + + a->api = api; + a->callback = cb; + a->userdata = userdata; + + a->io_event = api->io_new(api, a->fds[0], PA_IO_EVENT_INPUT, io_callback, a); + a->defer_event = api->defer_new(api, defer_callback, a); + a->api->defer_enable(a->defer_event, 0); + + a->n_queued_events = 0; + + return a; +} + +void pa_anotify_free(pa_anotify *a) { + assert(a); + + a->api->io_free(a->io_event); + a->api->defer_free(a->defer_event); + + if (a->fds[0] >= 0) + close(a->fds[0]); + if (a->fds[1] >= 0) + close(a->fds[1]); + + pa_xfree(a); +} + +int pa_anotify_signal(pa_anotify *a, uint8_t event) { + ssize_t r; + assert(a); + + r = write(a->fds[1], &event, 1); + return r != 1 ? -1 : 0; +} diff --git a/src/pulsecore/anotify.h b/src/pulsecore/anotify.h new file mode 100644 index 00000000..44e942f7 --- /dev/null +++ b/src/pulsecore/anotify.h @@ -0,0 +1,38 @@ +#ifndef foopulseanotifyhfoo +#define foopulseanotifyhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* Asynchronous thread-safe notification of mainloops */ + + +#include +#include + +typedef struct pa_anotify pa_anotify; +typedef void (*pa_anotify_cb_t)(uint8_t event, void *userdata); + +pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata); +void pa_anotify_free(pa_anotify *a); +int pa_anotify_signal(pa_anotify *a, uint8_t event); + +#endif -- cgit