From b2c341f935bd54eb1b7f80a297e72bf0e6c6dc83 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 19:51:14 +0000 Subject: add a threading primitive API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1344 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/mutex-posix.c | 121 +++++++++++++++++++++++++++++++++++ src/pulsecore/mutex.h | 39 ++++++++++++ src/pulsecore/thread-posix.c | 146 +++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/thread.h | 44 +++++++++++++ 4 files changed, 350 insertions(+) create mode 100644 src/pulsecore/mutex-posix.c create mode 100644 src/pulsecore/mutex.h create mode 100644 src/pulsecore/thread-posix.c create mode 100644 src/pulsecore/thread.h (limited to 'src/pulsecore') diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c new file mode 100644 index 00000000..d0156dbf --- /dev/null +++ b/src/pulsecore/mutex-posix.c @@ -0,0 +1,121 @@ +/* $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. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "mutex.h" + +#define ASSERT_SUCCESS(x) do { \ + int _r = (x); \ + assert(_r == 0); \ +} while(0) + +struct pa_mutex { + pthread_mutex_t mutex; +}; + +struct pa_cond { + pthread_cond_t cond; +}; + +pa_mutex* pa_mutex_new(int recursive) { + pa_mutex *m; + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + + if (recursive) + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) < 0) + return NULL; + + m = pa_xnew(pa_mutex, 1); + + if (pthread_mutex_init(&m->mutex, &attr) < 0) { + pa_xfree(m); + return NULL; + } + + return m; +} + +void pa_mutex_free(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_destroy(&m->mutex)); + pa_xfree(m); +} + +void pa_mutex_lock(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_lock(&m->mutex)); +} + +void pa_mutex_unlock(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_unlock(&m->mutex)); +} + + +pa_cond *pa_cond_new(void) { + pa_cond *c; + + c = pa_xnew(pa_cond, 1); + + if (pthread_cond_init(&c->cond, NULL) < 0) { + pa_xfree(c); + return NULL; + } + + return c; +} + +void pa_cond_free(pa_cond *c) { + assert(c); + + ASSERT_SUCCESS(pthread_cond_destroy(&c->cond)); + pa_xfree(c); +} + +void pa_cond_signal(pa_cond *c, int broadcast) { + assert(c); + + if (broadcast) + ASSERT_SUCCESS(pthread_cond_broadcast(&c->cond)); + else + ASSERT_SUCCESS(pthread_cond_signal(&c->cond)); +} + +int pa_cond_wait(pa_cond *c, pa_mutex *m) { + assert(c); + assert(m); + + return pthread_cond_wait(&c->cond, &m->mutex); +} diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h new file mode 100644 index 00000000..b3b9c5c6 --- /dev/null +++ b/src/pulsecore/mutex.h @@ -0,0 +1,39 @@ +#ifndef foopulsemutexhfoo +#define foopulsemutexhfoo + +/* $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. +***/ + +typedef struct pa_mutex pa_mutex; + +pa_mutex* pa_mutex_new(int recursive); +void pa_mutex_free(pa_mutex *m); +void pa_mutex_lock(pa_mutex *m); +void pa_mutex_unlock(pa_mutex *m); + +typedef struct pa_cond pa_cond; + +pa_cond *pa_cond_new(void); +void pa_cond_free(pa_cond *c); +void pa_cond_signal(pa_cond *c, int broadcast); +int pa_cond_wait(pa_cond *c, pa_mutex *m); + +#endif diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c new file mode 100644 index 00000000..15ade290 --- /dev/null +++ b/src/pulsecore/thread-posix.c @@ -0,0 +1,146 @@ +/* $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. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "thread.h" + +#define ASSERT_SUCCESS(x) do { \ + int _r = (x); \ + assert(_r == 0); \ +} while(0) + +struct pa_thread { + pthread_t id; + pa_thread_func_t thread_func; + void *userdata; + AO_t running; +}; + +struct pa_tls { + pthread_key_t key; +}; + +static pa_tls *thread_tls; +static pthread_once_t thread_tls_once = PTHREAD_ONCE_INIT; + +static void thread_tls_once_func(void) { + thread_tls = pa_tls_new(NULL); + assert(thread_tls); +} + +static void* internal_thread_func(void *userdata) { + pa_thread *t = userdata; + assert(t); + + t->id = pthread_self(); + + ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + pa_tls_set(thread_tls, t); + + AO_store_release_write(&t->running, 1); + t->thread_func(t->userdata); + AO_store_release_write(&t->running, 0); + + return NULL; +} + +pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { + pa_thread *t; + + t = pa_xnew(pa_thread, 1); + t->thread_func = thread_func; + t->userdata = userdata; + + if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) { + pa_xfree(t); + return NULL; + } + + return t; +} + +int pa_thread_is_running(pa_thread *t) { + assert(t); + + return !!AO_load_acquire_read(&t->running); +} + +void pa_thread_free(pa_thread *t) { + assert(t); + + pa_thread_join(t); + pa_xfree(t); +} + +int pa_thread_join(pa_thread *t) { + assert(t); + + return pthread_join(t->id, NULL); +} + +pa_thread* pa_thread_self(void) { + ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + return pa_tls_get(thread_tls); +} + +pa_tls* pa_tls_new(pa_free_cb_t free_cb) { + pa_tls *t; + + t = pa_xnew(pa_tls, 1); + + if (pthread_key_create(&t->key, free_cb) < 0) { + pa_xfree(t); + return NULL; + } + + return t; +} + +void pa_tls_free(pa_tls *t) { + assert(t); + + ASSERT_SUCCESS(pthread_key_delete(t->key)); + pa_xfree(t); +} + +void *pa_tls_get(pa_tls *t) { + assert(t); + + return pthread_getspecific(t->key); +} + +void *pa_tls_set(pa_tls *t, void *userdata) { + void *r; + + r = pthread_getspecific(t->key); + ASSERT_SUCCESS(pthread_setspecific(t->key, userdata)); + return r; +} + diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h new file mode 100644 index 00000000..978e9927 --- /dev/null +++ b/src/pulsecore/thread.h @@ -0,0 +1,44 @@ +#ifndef foopulsethreadhfoo +#define foopulsethreadhfoo + +/* $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. +***/ + +#include + +typedef struct pa_thread pa_thread; + +typedef void (*pa_thread_func_t) (void *userdata); + +pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata); +void pa_thread_free(pa_thread *t); +int pa_thread_join(pa_thread *t); +int pa_thread_is_running(pa_thread *t); +pa_thread *pa_thread_self(void); + +typedef struct pa_tls pa_tls; + +pa_tls* pa_tls_new(pa_free_cb_t free_cb); +void pa_tls_free(pa_tls *t); +void * pa_tls_get(pa_tls *t); +void *pa_tls_set(pa_tls *t, void *userdata); + +#endif -- cgit