[pulseaudio-discuss] [PATCH 1/2] pulsecore: srbchannel: Extract ringbuffer code into its own file

Ahmed S. Darwish darwish.07 at gmail.com
Mon Nov 28 03:56:27 UTC 2016


To solve a 10.0 release blocker, pacat is to use this ringbuffer
implementation for its own playback mode.

Matching the rest of global pulse code, the ring initialization
APIs should be more opaque and sizes should be in size_t rather
than integers. Nonetheless they're left as is out of care not
to modify the critical srbchannel code this late in the process.

While at it, further document the ringbuffer prototypes.

Signed-off-by: Ahmed S. Darwish <darwish.07 at gmail.com>
---
 src/Makefile.am            |  1 +
 src/pulsecore/ringbuffer.c | 63 +++++++++++++++++++++++++++++++++++++++
 src/pulsecore/ringbuffer.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++
 src/pulsecore/srbchannel.c | 48 +-----------------------------
 4 files changed, 139 insertions(+), 47 deletions(-)
 create mode 100644 src/pulsecore/ringbuffer.c
 create mode 100644 src/pulsecore/ringbuffer.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 2d5bdd4..1fb7286 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -692,6 +692,7 @@ libpulsecommon_ at PA_MAJORMINOR@_la_SOURCES = \
 		pulsecore/lock-autospawn.c pulsecore/lock-autospawn.h \
 		pulsecore/log.c pulsecore/log.h \
 		pulsecore/ratelimit.c pulsecore/ratelimit.h \
+		pulsecore/ringbuffer.c pulsecore/ringbuffer.h \
 		pulsecore/macro.h \
 		pulsecore/mcalign.c pulsecore/mcalign.h \
 		pulsecore/memblock.c pulsecore/memblock.h \
diff --git a/src/pulsecore/ringbuffer.c b/src/pulsecore/ringbuffer.c
new file mode 100644
index 0000000..b025cfc
--- /dev/null
+++ b/src/pulsecore/ringbuffer.c
@@ -0,0 +1,63 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014 David Henningsson, Canonical Ltd.
+
+  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, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <pulsecore/atomic.h>
+#include "ringbuffer.h"
+
+void *pa_ringbuffer_peek(pa_ringbuffer *r, int *count) {
+    int c = pa_atomic_load(r->count);
+
+    if (r->readindex + c > r->capacity)
+        *count = r->capacity - r->readindex;
+    else
+        *count = c;
+
+    return r->memory + r->readindex;
+}
+
+/* Returns true only if the buffer was completely full before the drop. */
+bool pa_ringbuffer_drop(pa_ringbuffer *r, int count) {
+    bool b = pa_atomic_sub(r->count, count) >= r->capacity;
+
+    r->readindex += count;
+    r->readindex %= r->capacity;
+
+    return b;
+}
+
+void *pa_ringbuffer_begin_write(pa_ringbuffer *r, int *count) {
+    int c = pa_atomic_load(r->count);
+
+    *count = PA_MIN(r->capacity - r->writeindex, r->capacity - c);
+
+    return r->memory + r->writeindex;
+}
+
+void pa_ringbuffer_end_write(pa_ringbuffer *r, int count) {
+    pa_atomic_add(r->count, count);
+    r->writeindex += count;
+    r->writeindex %= r->capacity;
+}
diff --git a/src/pulsecore/ringbuffer.h b/src/pulsecore/ringbuffer.h
new file mode 100644
index 0000000..11493c3
--- /dev/null
+++ b/src/pulsecore/ringbuffer.h
@@ -0,0 +1,74 @@
+#ifndef foopulseringbufferhfoo
+#define foopulseringbufferhfoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014 David Henningsson, Canonical Ltd.
+
+  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, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef struct pa_ringbuffer pa_ringbuffer;
+
+struct pa_ringbuffer {
+    /* Initialize those before use */
+    pa_atomic_t *count;          /* Amount of data yet to be read/consumed */
+    int capacity;                /* Total ringbuffer size */
+    uint8_t *memory;             /* Actual backend memory */
+
+    /* <-- Private --> */
+    int readindex, writeindex;
+};
+
+/** Inquire about the amount of data that can be read
+ *
+ * @count: return argument; suggested amount of data to be read
+ *
+ * Note that if the amount of data to be read crosses the backend
+ * memory physical end, this method will suggest reading up only
+ * to that end. This is explicitly done to avoid extra memory
+ * copies.
+ *
+ * Thus to read the whole data available in the ring, run a loop
+ * of pa_ringbuffer_peek() and pa_ringbuffer_drop() until the
+ * returned @count is zero.
+ *
+ * Return a pointer to the buffer where data can be read from. */
+void *pa_ringbuffer_peek(pa_ringbuffer *r, int *count);
+
+/** Move the read index by @count bytes. Must be used after reading
+ * from the buffer returned by pa_ringbuffer_peek().
+ *
+ * Returns true only if buffer was completely full before the drop. */
+bool pa_ringbuffer_drop(pa_ringbuffer *r, int count);
+
+/** Inquire about the amount of data that can be written
+ *
+ * @count: return argument; suggested amount of data to be written
+ *
+ * Like pa_ringbuffer_peek(), if the amount of data that can be
+ * written crosses the backend memory phsyical end, this method
+ * will not cycle and provide a ring emulation. Build a loop of
+ * begin_write() and end_write(), until returned @count is zero,
+ * to write as much data to the ring as possible.
+ *
+ * Return a pointer to the buffer where data can be written to. */
+void *pa_ringbuffer_begin_write(pa_ringbuffer *r, int *count);
+
+/** Move the write index by @count bytes. Must be used after
+ * writing to the buffer returned by pa_ringbuffer_begin_write() */
+void pa_ringbuffer_end_write(pa_ringbuffer *r, int count);
+
+#endif
diff --git a/src/pulsecore/srbchannel.c b/src/pulsecore/srbchannel.c
index 4cdfaa7..59edc2a 100644
--- a/src/pulsecore/srbchannel.c
+++ b/src/pulsecore/srbchannel.c
@@ -24,57 +24,11 @@
 #include "srbchannel.h"
 
 #include <pulsecore/atomic.h>
+#include <pulsecore/ringbuffer.h>
 #include <pulse/xmalloc.h>
 
 /* #define DEBUG_SRBCHANNEL */
 
-/* This ringbuffer might be useful in other contexts too, but
- * right now it's only used inside the srbchannel, so let's keep it here
- * for the time being. */
-typedef struct pa_ringbuffer pa_ringbuffer;
-
-struct pa_ringbuffer {
-    pa_atomic_t *count; /* amount of data in the buffer */
-    int capacity;
-    uint8_t *memory;
-    int readindex, writeindex;
-};
-
-static void *pa_ringbuffer_peek(pa_ringbuffer *r, int *count) {
-    int c = pa_atomic_load(r->count);
-
-    if (r->readindex + c > r->capacity)
-        *count = r->capacity - r->readindex;
-    else
-        *count = c;
-
-    return r->memory + r->readindex;
-}
-
-/* Returns true only if the buffer was completely full before the drop. */
-static bool pa_ringbuffer_drop(pa_ringbuffer *r, int count) {
-    bool b = pa_atomic_sub(r->count, count) >= r->capacity;
-
-    r->readindex += count;
-    r->readindex %= r->capacity;
-
-    return b;
-}
-
-static void *pa_ringbuffer_begin_write(pa_ringbuffer *r, int *count) {
-    int c = pa_atomic_load(r->count);
-
-    *count = PA_MIN(r->capacity - r->writeindex, r->capacity - c);
-
-    return r->memory + r->writeindex;
-}
-
-static void pa_ringbuffer_end_write(pa_ringbuffer *r, int count) {
-    pa_atomic_add(r->count, count);
-    r->writeindex += count;
-    r->writeindex %= r->capacity;
-}
-
 struct pa_srbchannel {
     pa_ringbuffer rb_read, rb_write;
     pa_fdsem *sem_read, *sem_write;

-- 
Darwish
http://darwish.chasingpointers.com


More information about the pulseaudio-discuss mailing list