diff options
author | Lennart Poettering <lennart@poettering.net> | 2006-09-08 15:43:44 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2006-09-08 15:43:44 +0000 |
commit | bfaa3584581c0d9f3acc7208a0d7ab13845124ab (patch) | |
tree | b2f2b977224f2f6eb75ef99abbbb2bd00a619b5b /src/pulsecore | |
parent | 791bbd8e0e8b0a2350ee20321578f34ca026cd0e (diff) |
add a tiny wrapper around libatomic_ops: pa_atomic_int_t and pa_atomit_ptr_t.
Reasoning:
This wrapper fixes a few API issues I found with atomic_ops:
* AO_t is an int, which can be written to with "=". pa_tomic_int_t however is
a struct which due to type-safety enforces proper access with
pa_atomic_xx(). (Inspired by the way the Linux kernel handles this)
* AO_load()'s parameter is lacking a "const"
* Explicitly choosing the proper memory barrier for each call is very
difficult and especially hard to debug because most CPUs support only two
different barrier types which the eight types defined by atomic_ops are
mapped to. Most other software (i.e. glib, Linux kernel) which provides
atomic variable access usually do a full barrier in all cases and so should
we. Eventually we might choose to add additional memory barrier calls, in
which case we can add special versions of the current function with special
suffixes.
* The function names are unnecesarily long
* Atomic pointer accesses are only supported with manual casts.
The new pa_atomic_xxx interface borrows heavily from the GLib and Linux kernel
atomicity API, though it is different from both of them.
In addition this abstract API makes it easy to port PA to different atomicty
APIs, if libatomic_ops should ever become out-of-fashion or if the system OS
supports atomic primitives anyway.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1381 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/pulsecore')
-rw-r--r-- | src/pulsecore/atomic.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h new file mode 100644 index 00000000..f789142d --- /dev/null +++ b/src/pulsecore/atomic.h @@ -0,0 +1,80 @@ +#ifndef foopulseatomichfoo +#define foopulseatomichfoo + +/* $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 <atomic_ops.h> + +/* atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). + * + * It is not guaranteed however, that sizeof(AO_t) == sizeof(size_t). + * however very likely. */ + +typedef struct pa_atomic_int { + volatile AO_t value; +} pa_atomic_int_t; + +/* For now we do only full memory barriers. Eventually we might want + * to support more elaborate memory barriers, in which case we will add + * suffixes to the function names */ + +static inline int pa_atomic_load(const pa_atomic_int_t *a) { + return (int) AO_load_full((AO_t*) &a->value); +} + +static inline void pa_atomic_store(pa_atomic_int_t *a, int i) { + AO_store_full(&a->value, (AO_t) i); +} + +static inline int pa_atomic_add(pa_atomic_int_t *a, int i) { + return AO_fetch_and_add_full(&a->value, (AO_t) i); +} + +static inline int pa_atomic_inc(pa_atomic_int_t *a) { + return AO_fetch_and_add1_full(&a->value); +} + +static inline int pa_atomic_dec(pa_atomic_int_t *a) { + return AO_fetch_and_sub1_full(&a->value); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_int_t *a, int old_i, int new_i) { + return AO_compare_and_swap_full(&a->value, old_i, new_i); +} + +typedef struct pa_atomic_ptr { + volatile AO_t value; +} pa_atomic_ptr_t; + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + return (void*) AO_load_full((AO_t*) &a->value); +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + AO_store_full(&a->value, (AO_t) p); +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + return AO_compare_and_swap_full(&a->value, (AO_t) old_p, (AO_t) new_p); +} + +#endif |