From 250eafdb48c39ea2bfa2cb3b5887996e96aea632 Mon Sep 17 00:00:00 2001 From: Martin Piatka Date: Mon, 30 Aug 2021 14:52:49 +0200 Subject: [PATCH] ring_buffer: expose the zero-copy interface --- src/utils/ring_buffer.cpp | 12 ++++----- src/utils/ring_buffer.h | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/utils/ring_buffer.cpp b/src/utils/ring_buffer.cpp index da7c12de6..ca33472a1 100644 --- a/src/utils/ring_buffer.cpp +++ b/src/utils/ring_buffer.cpp @@ -93,7 +93,7 @@ static int calculate_avail_write(int start, int end, int buf_len) { } -static int ring_get_read_regions(struct ring_buffer *ring, int max_len, +int ring_get_read_regions(struct ring_buffer *ring, int max_len, void **ptr1, int *size1, void **ptr2, int *size2) { @@ -124,7 +124,7 @@ static int ring_get_read_regions(struct ring_buffer *ring, int max_len, return read_len; } -static void ring_advance_read_idx(struct ring_buffer *ring, int amount) { +void ring_advance_read_idx(struct ring_buffer *ring, int amount) { // start index is modified only by this (reader) thread, so relaxed is enough int start = std::atomic_load_explicit(&ring->start, std::memory_order_relaxed); @@ -161,7 +161,7 @@ void ring_buffer_flush(struct ring_buffer * buf) { buf->end = 0; } -static bool ring_get_write_regions(struct ring_buffer *ring, int requested_len, +int ring_get_write_regions(struct ring_buffer *ring, int requested_len, void **ptr1, int *size1, void **ptr2, int *size2) { @@ -174,7 +174,7 @@ static bool ring_get_write_regions(struct ring_buffer *ring, int requested_len, int end = std::atomic_load_explicit(&ring->end, std::memory_order_relaxed); if(requested_len > ring->len) { - return false; + return 0; } int end_idx = end % ring->len; @@ -186,10 +186,10 @@ static bool ring_get_write_regions(struct ring_buffer *ring, int requested_len, *size2 = requested_len - *size1; } - return true; + return *size1 + *size2; } -static bool ring_advance_write_idx(struct ring_buffer *ring, int amount) { +bool ring_advance_write_idx(struct ring_buffer *ring, int amount) { const int start = std::atomic_load_explicit(&ring->start, std::memory_order_acquire); // end index is modified only by this (writer) thread, so relaxed is enough const int end = std::atomic_load_explicit(&ring->end, std::memory_order_relaxed); diff --git a/src/utils/ring_buffer.h b/src/utils/ring_buffer.h index 9d82e9a65..b9b02c281 100644 --- a/src/utils/ring_buffer.h +++ b/src/utils/ring_buffer.h @@ -84,6 +84,59 @@ int ring_get_current_size(struct ring_buffer * ring); */ int ring_get_available_write_size(struct ring_buffer * ring); + +/** + * Returns pointers to memory available for reading. After reading use + * ring_advance_read_idx() to mark the memory as free for writing. + * + * @param max_len cap returned size to this value + * @param ptr1 pointer to the first region + * @param size1 size of available data in the first region + * @param ptr2 pointer to the second region + * @param size2 size of available data in the second region + * @return size1 + size2 + */ +int ring_get_read_regions(struct ring_buffer *ring, int max_len, + void **ptr1, int *size1, + void **ptr2, int *size2); + +/** + * Marks memory as already read and free for writing. Use after reading using + * ring_get_read_regions(), or simply for discarding unwanted unread data. + * + * @param amount amount in bytes to discard + */ +void ring_advance_read_idx(struct ring_buffer *ring, int amount); + +/** + * Returns pointers to memory available for writing. After writing use + * ring_advance_write_idx() to mark the memory as available for reading. + * + * Does not check for overflow, returns regions of requested size even if + * buffer is full. + * + * If the requested_len is longer than the whole buffer, returns 0. + * + * @param requested_len amount you want to write + * @param ptr1 pointer to the first region + * @param size1 size of the first region + * @param ptr2 pointer to the second region + * @param size2 size of the second region + * @return size1 + size2 + */ +int ring_get_write_regions(struct ring_buffer *ring, int requested_len, + void **ptr1, int *size1, + void **ptr2, int *size2); + +/** + * Marks written memory as ready for reading. Use after writing using + * ring_get_write_regions(). + * + * @param amount amount in bytes to discard + * @return true if an overflow occured + */ +bool ring_advance_write_idx(struct ring_buffer *ring, int amount); + extern struct audio_buffer_api ring_buffer_fns; #ifdef __cplusplus