Skip to content

Commit

Permalink
Merge branch 'develop-feature-overwrite' into fix_rollover_bug
Browse files Browse the repository at this point in the history
  • Loading branch information
jnz86 authored Jan 16, 2023
2 parents 0fe17b4 + b056597 commit d7507c4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 42 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"string.h": "c",
"lwevt_opt.h": "c",
"stdatomic.h": "c",
"lwrb.h": "c"
"lwrb.h": "c",
"*.tcc": "c"
},
"esbonio.sphinx.confDir": ""
}
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ else()
# Add subdir with lwrb and link to project
add_subdirectory(lwrb)
target_link_libraries(${PROJECT_NAME} lwrb)
target_link_libraries(${PROJECT_NAME} lwrb_ex)
endif()
3 changes: 3 additions & 0 deletions lwrb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ message("Entering ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
add_library(lwrb INTERFACE)
target_sources(lwrb PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c)
target_include_directories(lwrb INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include)
add_library(lwrb_ex INTERFACE)
target_sources(lwrb_ex PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb_ex.c)
target_include_directories(lwrb_ex INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include)

# Register other modules

Expand Down
97 changes: 56 additions & 41 deletions lwrb/src/lwrb/lwrb_ex.c
Original file line number Diff line number Diff line change
@@ -1,15 +1,44 @@
/**
* \file lwrb_ex.c
* \brief Lightweight ring buffer extended functions
* \brief Lightweight ring buffer - extended functions
*/


#include "lwrb.h"

/*
* Copyright (c) 2022 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <[email protected]>
* Version: v3.0.0-rc1
*/
#include "lwrb/lwrb.h"

#define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0)
#define BUF_MIN(x, y) ((x) < (y) ? (x) : (y))

#ifndef LWRB_DEV
#error "This file needs development & extensive tests - not to be used!"
#endif

/**
* \brief Similar to write(), writes data to buffer, will overwrite existing values.
Expand All @@ -22,47 +51,42 @@
* it. This operation is a read op as well as a write op. For thread-safety mutexes may be desired,
* see documentation.
*/
size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw)
{
size_t
lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw) {
size_t w, r, linear, wrap;
size_t size = buff->size;
size_t size = buff->size;
size_t offset = 0;

if (!BUF_IS_VALID(buff) || data == NULL || btw == 0)
{
if (!BUF_IS_VALID(buff) || data == NULL || btw == 0) {
return 0;
}

w = atomic_load_explicit(&buff->w, memory_order_relaxed);
r = atomic_load_explicit(&buff->r, memory_order_relaxed);



/* Step 1: Special handling if asked to write more bytes than size. */
if (btw >= size)
{
if (btw >= size) {
offset = (btw - size) + 1;
btw = size - 1;
btw = size - 1;
}



/* Step 2: Always write the linear region. There will be at least one byte written here. */

/* Handle special case of linear being off by one when zero */ // TODO: Test this
if (w == 0)
/* Handle special case of linear being off by one when zero */ // TODO: Test this
if (w == 0) {
linear = size - 1;
else
} else {
linear = size - w;
}

/* We might not need the whole linear length available, depends on amount to write*/
if (btw < linear)
if (btw < linear) {
linear = btw;
}

/* If linear write will exceed r it must be updated, this may also happen in wrap region later
*/
if ((w < r) && (w + linear) > r)
{
if ((w < r) && (w + linear) > r) {
r = w + btw + 1;
r %= size;
}
Expand All @@ -73,15 +97,11 @@ size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw)
w %= size;
wrap = btw - linear;



/* Step 3: Wrap region are the bytes that rolled back to the start of the storage array */
if (wrap)
{
if (wrap) {

/* If r will be overrun by new write data, skip r ahead */
if ((w <= r) && (w + wrap) >= r)
{
if ((w <= r) && (w + wrap) >= r) {
r = w + wrap + 1;
// r %= size; // TODO: Can this happen now?
}
Expand All @@ -92,8 +112,6 @@ size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw)
w %= size;
}



/* Step 4: The ring buffer is complete, this is a write op as well as possibly a read op */
atomic_store_explicit(&buff->w, w, memory_order_release);
atomic_store_explicit(&buff->r, r, memory_order_release);
Expand All @@ -105,8 +123,6 @@ size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw)
return (btw);
}



/**
* \brief Copy one ring buffer to another, upto the amount of data in the source, or amount
* of data free in the destination.
Expand All @@ -117,32 +133,31 @@ size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw)
* As well as a write op to the destination, and may update the w index. For thread-safety mutexes may
* be desired, see documentation.
*/
size_t lwrb_copy(lwrb_t* dest, lwrb_t* src)
{
size_t
lwrb_copy(lwrb_t* dest, lwrb_t* src) {
size_t dest_w, src_r;
size_t len_to_copy = BUF_MIN(lwrb_get_full(src), lwrb_get_free(dest));
size_t i;

if (!BUF_IS_VALID(dest) || !BUF_IS_VALID(src))
{
if (!BUF_IS_VALID(dest) || !BUF_IS_VALID(src)) {
return 0;
}

dest_w = atomic_load_explicit(&dest->w, memory_order_relaxed);
src_r = atomic_load_explicit(&src->r, memory_order_relaxed);
src_r = atomic_load_explicit(&src->r, memory_order_relaxed);

/* For the lesser amount in source or free in destination, copy byte by byte */
for (i = 0; i < len_to_copy; i++)
{
for (i = 0; i < len_to_copy; i++) {

dest->buff[dest_w++] = src->buff[src_r++];

/* Handle roll-over / wrap for both source and destination indexes */
if (dest_w >= dest->size)
if (dest_w >= dest->size) {
dest_w = 0;
if (src_r >= src->size)
src_r = 0;
}
}


atomic_store_explicit(&dest->w, dest_w, memory_order_release);
atomic_store_explicit(&src->r, src_r, memory_order_release);
Expand Down

0 comments on commit d7507c4

Please sign in to comment.