Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
MaJerle committed Dec 21, 2023
2 parents 465b2fb + c7fe6fd commit 1aea601
Show file tree
Hide file tree
Showing 21 changed files with 362 additions and 120 deletions.
19 changes: 19 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
Checks: "*,
-abseil-*,
-altera-*,
-android-*,
-fuchsia-*,
-google-*,
-llvm*,
-modernize-use-trailing-return-type,
-zircon-*,
-readability-else-after-return,
-readability-static-accessed-through-instance,
-readability-avoid-const-params-in-decls,
-cppcoreguidelines-non-private-member-variables-in-classes,
-misc-non-private-member-variables-in-classes,
"
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none
18 changes: 18 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py

# Python configuration
python:
install:
- requirements: docs/requirements.txt

formats:
- pdf
- epub
9 changes: 9 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Tilen Majerle <tilen.majerle@gmail.com>
Tilen Majerle <tilen@majerle.eu>
Jaedeok Kim <jdeokkim@protonmail.com>
Thomas Devoogdt <thomas@devoogdt.com>
LinJieqiang <517503838@qq.com>
jnz86 <jumpifnotzero@gmail.com>
Junde Yhi <junde@yhi.moe>
Jackistang <tangjia.jackis@qq.com>
Tofik Sonono <tofik@sonono.me>
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

## Develop

## v3.1.0

- Preparation for `v3.1`
- Replace `size_t` with custom defined type `lwrb_sz_t` which matches atomicity requirements
- `lwrb_sz_t` is by default typedef-ed as `unsigned long`
- Prepare `lwrb_write_ex` and `lwrb_read_ex` functions
- Implement `lwrb_write_ex` and `lwrb_read_ex` functions
- Fix `_ex` module throwing an error for Platform.IO

## v3.0.0

- Added macros for optional STDATOMIC. Global `-DLWRB_DISABLE_ATOMIC` macro will disable C11 `<stdatomic.h>` functionality.
- Add `lwrb_move` and `lwrb_overwrite`
- Fix `lwrb_find` which failed to properly search for tokens at corner cases

## v3.0.0-RC1
## v3.1.0-RC1

- Split CMakeLists.txt files between library and executable
- Change license year to 2022
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ else()
WIN32
_DEBUG
CONSOLE
LWRB_DEV
)

# Compiler options
Expand All @@ -35,6 +34,7 @@ else()
)

# Add subdir with lwrb and link to project
set(LWRB_COMPILE_DEFINITIONS LWRB_DEV)
add_subdirectory(lwrb)
target_link_libraries(${PROJECT_NAME} lwrb)
target_link_libraries(${PROJECT_NAME} lwrb_ex)
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ Library provides generic FIFO ring buffer implementation.
* Uses optimized memory copy instead of loops to read/write data from/to memory
* Thread safe when used as pipe with single write and single read entries - when CPU read/write operation for `size_t` are single instruction (ARM Cortex-M for instance)
* Interrupt safe when used as pipe with single write and single read entries - when CPU read/write operation for `size_t` are single instruction (ARM Cortex-M for instance)
* For CPU systems with smaller achitecture than `sizeof(size_t)` (AVR for instance), atomic protection is required for read-write operation of buffer writes
* For CPU systems with smaller architecture than `sizeof(size_t)` (AVR for instance), atomic protection is required for read-write operation of buffer writes
* Suitable for DMA transfers from and to memory with zero-copy overhead between buffer and application memory
* Supports data peek, skip for read and advance for write
* Implements support for event notifications
* User friendly MIT license

## Contribute

Fresh contributions are always welcome. Simple instructions to proceed::
Fresh contributions are always welcome. Simple instructions to proceed:

1. Fork Github repository
2. Follow [C style & coding rules](https://github.com/MaJerle/c-code-style) already used in the project
Expand All @@ -30,4 +30,4 @@ Fresh contributions are always welcome. Simple instructions to proceed::
Alternatively you may:

1. Report a bug
2. Ask for a feature request
2. Ask for a feature request
44 changes: 40 additions & 4 deletions dev/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ lwrb_t buff;
uint8_t tmp[8];

void
my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, size_t len) {
my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, lwrb_sz_t len) {
(void)buff;
(void)len;
switch (type) {
Expand All @@ -25,7 +25,7 @@ my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, size_t len) {

int
main() {
size_t len;
lwrb_sz_t len;

/* Init buffer */
lwrb_init(&buff, lwrb_data, sizeof(lwrb_data));
Expand Down Expand Up @@ -54,6 +54,42 @@ main() {
len = lwrb_write(&buff, "abc", 3); /* Write 3 bytes -> buffer should go over */
RW_TEST(0, 6, len, 3);

#undef RW_TEST
}

printf("Read/Write extended test\r\n");
{
uint8_t rw_buff[8];
lwrb_sz_t written, read;
uint8_t success;

#define RW_TEST(_w_exp_, _r_exp_, _success_, _rw_len_, _rw_exp_len_) \
do { \
printf("W ptr: %u, R ptr: %u, R/W success: %u, R/W len: %u, as_expected: %u\r\n", (unsigned)buff.w, \
(unsigned)buff.r, (unsigned)(_success_), (unsigned)(_rw_len_), \
(unsigned)(buff.w == (_w_exp_) && buff.r == (_r_exp_) && (_rw_len_) == (_rw_exp_len_))); \
} while (0)

lwrb_reset(&buff);
written = 0;
success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */
RW_TEST(7, 0, success, written, 7);
success = lwrb_read_ex(&buff, rw_buff, 3, &read, LWRB_FLAG_READ_ALL); /* Read 3 bytes only */
printf("RW FULL READ: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1));
RW_TEST(7, 3, success, written, 7);

/* This one shall failed, not enough memory available */
success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */
printf("RW FULL WRITE: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 0));

/* Read few more bytes to allow full write */
success = lwrb_read_ex(&buff, rw_buff, 3, &read, LWRB_FLAG_READ_ALL); /* Read 3 bytes only */
printf("RW FULL READ: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1));

/* Now it should go through */
success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */
printf("RW FULL WRITE: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1));

#undef RW_TEST
}

Expand Down Expand Up @@ -99,7 +135,7 @@ main() {
{
#define MOVE_TEST(_exp_content_, _exp_move_len_, _exp_buff_len_) \
do { \
size_t move_len; \
lwrb_sz_t move_len; \
move_len = lwrb_move(&dst, &src); \
len = lwrb_peek(&dst, 0, tmp, dst.size); \
printf("move data: len: %d, dest data: %.*s, as_expected: %u\r\n", (int)len, (int)len, tmp, \
Expand Down Expand Up @@ -137,7 +173,7 @@ main() {
{
#define FIND_TEST(_bts_, _bts_len_, _start_offset_, _exp_result_) \
do { \
size_t found_idx; \
lwrb_sz_t found_idx; \
uint8_t found; \
found = lwrb_find(&buff, (_bts_), (_bts_len_), (_start_offset_), &found_idx); \
printf("Find \"%s\" (len %d), start_offset: %d, found_index: %d; Found: %d; As expected: %d\r\n", (_bts_), \
Expand Down
8 changes: 8 additions & 0 deletions docs/authors/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. _authors:

Authors
=======

List of authors and contributors to the library

.. literalinclude:: ../../AUTHORS
12 changes: 11 additions & 1 deletion docs/get-started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,17 @@ Add library to project
^^^^^^^^^^^^^^^^^^^^^^

At this point it is assumed that you have successfully download library, either cloned it or from releases page.
Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path
Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path.

*CMake* is the main supported build system. Package comes with the ``CMakeLists.txt`` and ``library.cmake`` files, both located in the ``lwrb`` directory:

* ``CMakeLists.txt``: Is a wrapper and only includes ``library.cmake`` file. It is used if target application uses ``add_subdirectory`` and then uses ``target_link_libraries`` to include the library in the project
* ``library.cmake``: It is a fully configured set of variables. User must use ``include(path/to/library.cmake)`` to include the library and must manually add files/includes to the final target

.. tip::
Open ``library.cmake`` file and manually analyze all the possible variables you can set for full functionality.

If you do not use the *CMake*, you can do the following:

* Copy ``lwrb`` folder to your project, it contains library files
* Add ``lwrb/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Table of contents
tips-tricks/index
api-reference/index
changelog/index
authors/index

.. toctree::
:maxdepth: 2
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
sphinx>=3.5.1
breathe>=4.9.1
urllib3==1.26.15
urllib3==1.26.18
docutils==0.16
colorama
sphinx_rtd_theme>=1.0.0
Expand Down
26 changes: 22 additions & 4 deletions docs/user-manual/thread-safety.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Thread safety
=============

Ring buffers are effectively used in embedded systems with or without operating systems.
Common problem most of implementations have is linked to multi-thread environment (when using OS) or reading/writing from/to interrupts.
This is linked to common question *What happens if I write to buffer while another thread is reading from it?*
Common problem most of implementations have, is linked to multi-thread environment (when using OS) or reading/writing from/to interrupts.
Question becomes *What happens if I write to buffer while another thread is reading from it?*

One of the main requirements (beside being lightweight) of *LwRB* was to allow *read-while-write* or *write-while-read* operations.
This is achieved only when there is single write entry point and single read exit point.
Expand All @@ -31,8 +31,8 @@ Therefore multiple *conditional* checks are guaranteed to be performed on the sa

.. note::
Even single entry and single exit points may introduce race condition, especially on smaller system, such as 8-bit or 16-bit system, or in general,
where arbitrary type (normaly `size_t`) is `sizeof(type) < architecture_size`.
This is solved by C11 atomic library, that ensures atomic reads and writes to key structure members
where arbitrary type (normaly `size_t`) is `sizeof(type) > architecture_size`.
This is solved by C11 atomic library, that ensures atomic reads and writes to key structure members.

Thread safety gets completely broken when application does one of the following:

Expand Down Expand Up @@ -94,3 +94,21 @@ access is granted to *read* operation while *write* operation from one thread ta

.. toctree::
:maxdepth: 2

Atomicity
=========

While thread-safety concepts are very important, depending on the system architecture and variable sizes (and hardware cache),
application must also ensure that all the writes and reads to the internal variables are executed in atomic manner.

Especially critical case is when read/write from/to variable isn't ``1`` cycle on specific architecture (for instance 32-bit variable on 8-bit CPU).

Library (in its default configuration) uses ``stdatomic`` feature from *C11* language, and relies on a compiler to properly
generate necessary calls to make sure, all reads and writes are atomic.

.. note::
Atomicity is required even if ring buffer is configured in *fifo* mode, with single write point and single read point.

.. tip::
You can disable atomic operations in the library, by defining ``LWRB_DISABLE_ATOMIC`` global macro (typically with ``-D`` compiler option).
It is then up to the developer to make sure architecture properly handles atomic operations.
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "LwRB",
"version": "3.0.0",
"version": "3.1.0",
"description": "Lightweight general purpose ring buffer with optimizations for embedded systems",
"keywords": "buffer, ring buffer, library, rb, cyclic",
"repository": {
Expand Down
10 changes: 1 addition & 9 deletions lwrb/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
cmake_minimum_required(VERSION 3.22)

# Register core library
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
include(${CMAKE_CURRENT_LIST_DIR}/library.cmake)
38 changes: 38 additions & 0 deletions lwrb/library.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# This file provides set of variables for end user
# and also generates one (or more) libraries, that can be added to the project using target_link_libraries(...)
#
# Before this file is included to the root CMakeLists file (using include() function), user can set some variables:
#
# LWRB_COMPILE_OPTIONS: If defined, it provide compiler options for generated library.
# LWRB_COMPILE_DEFINITIONS: If defined, it provides "-D" definitions to the library build
#

# Library core sources
set(lwrb_core_SRCS
${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c
)

# Library extended sources
set(lwrb_ex_SRCS
${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb_ex.c
)

# Setup include directories
set(lwrb_include_DIRS
${CMAKE_CURRENT_LIST_DIR}/src/include
)

# Register library to the system
add_library(lwrb)
target_sources(lwrb PUBLIC ${lwrb_core_SRCS})
target_include_directories(lwrb PUBLIC ${lwrb_include_DIRS})
target_compile_options(lwrb PUBLIC ${LWRB_COMPILE_OPTIONS})
target_compile_definitions(lwrb PUBLIC ${LWRB_COMPILE_DEFINITIONS})

# Register extended part
add_library(lwrb_ex)
target_sources(lwrb_ex PUBLIC ${lwrb_ex_SRCS})
target_include_directories(lwrb_ex PUBLIC ${lwrb_include_DIRS})
target_compile_options(lwrb_ex PUBLIC ${LWRB_COMPILE_OPTIONS})
target_compile_definitions(lwrb_ex PUBLIC ${LWRB_COMPILE_DEFINITIONS} LWRB_EXTENDED)
Loading

0 comments on commit 1aea601

Please sign in to comment.