From c4f1ede6b01c5a66d211e94ed295a4e34c05373b Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Tue, 2 Jul 2024 05:39:21 +0200 Subject: [PATCH] rb_push_many first draft --- ringbuf.c | 41 +++++++++++++++++++++++++++++++++++++++++ ringbuf.h | 22 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/ringbuf.c b/ringbuf.c index 5c004ba..d0b4621 100644 --- a/ringbuf.c +++ b/ringbuf.c @@ -63,6 +63,47 @@ rb_push_back(struct RingBuf *rb, const void *item, MEMCPY_T memcpy_fn) return WriteOk; } +enum WriteResult +rb_push_many(struct RingBuf *rb, const void *items, MEMCPY_T memcpy_fn, + rb_size_t n) +{ + if(rb->count + n > rb->capacity) + return Full; // Perhaps rename to InsufficientSpace + + // If the write head will move past the end of the buffer + // we need to to the write in two steps. + void *end = (char *)rb->write_head + rb->struct_size * n; + + if(end > rb->buffer_end) { + + // Calculate the number of items that can be written in the first chunk + rb_size_t first_chunk = (char *)rb->buffer_end - (char *)rb->write_head; + + DEBUG_PRINT("Multi-chunk write. First chunk: %d\n", first_chunk); + + // Write the first chunk + memcpy_fn(rb->write_head, items, rb->struct_size * first_chunk); + + // Set the write head to the beginning of the buffer + rb->write_head = rb->buffer; + rb->count += first_chunk; + n -= first_chunk; + } else { + DEBUG_PRINT("Single-chunk write. No need to wrap around.%s\n", ""); + } + + DEBUG_PRINT("Writing %d items\n", n); + memcpy_fn(rb->write_head, items, rb->struct_size * n); + if(rb->write_head == rb->buffer_end) + rb->write_head = rb->buffer; + + // Advance the write head + rb->write_head = (char *)rb->write_head + rb->struct_size * n; + rb->count+=n; + + return WriteOk; +} + enum ReadResult rb_pop_front(struct RingBuf *rb, void *item) { diff --git a/ringbuf.h b/ringbuf.h index a017a7f..f374bac 100644 --- a/ringbuf.h +++ b/ringbuf.h @@ -49,6 +49,28 @@ void rb_init(struct RingBuf *rb, rb_size_t capacity, ALLOC_T alloc, enum WriteResult rb_push_back(struct RingBuf *rb, const void *item, MEMCPY_T memcpy_fn); +/** + * @brief Insert multiple data to the ring buffer + * + * @details This function is more efficient than calling rb_push_back multiple + * times. It only advances the write head once, and attempts to write all the + * memory in one go. + * + * If n is greater than the capacity, it will return Full. + * If the full write will overflow, it will wrap around. + * + * If the buffer is full, it will return Full and not write + * anything. + * + * @param rb The ring buffer + * @param items The items to insert + * @param memcpy_fn The memcpy function + * @param n The number of items to insert + * @return WriteResult + */ +enum WriteResult rb_push_many(struct RingBuf *rb, const void *items, + MEMCPY_T memcpy_fn, rb_size_t n); + /** * @brief Read data from the ring buffer * @param rb The ring buffer