spms_ring
is a single publisher multiple subscriber ring buffer suitable for shared memory.
The publisher writes messages to the ring without being aware of the subscribers.
When a subscriber reads a message, it is not removed from the ring and still can
be read by other subscribers. If a subscriber is not fast enough to read the messages, it will miss some of them.
Besides the usual read and write functions, I wanted the ring to have the following features:
- Timestamps can be added to the messages and subscribers can read from a specific timestamp on.
- Messages can be marked as key messages (Like key frames in video streams) and subscribers can jump to the next key message.
- A zero copy API.
- Optionally letting the subscriber wait for new messages if the ring is empty.
Currently only Linux and MacOS are fully supported. The wait for new messages feature is not implemented for Windows, but it should be easy to do so.
git clone git@github.com:RaphiaRa/spms_ring.git
mkdir spms_ring/build; cd spms_ring/build
cmake ..
make
Run the tests with
./test_spms
Run the example publisher
./example pub
Run the example subscriber in one or multiple other terminals
./example sub
Either...
- simply copy
spms.h
andspms.c
into your project and includespms.h
in your source files. - or use CMake's
add_subdirectory
to addspms_ring
as a subdirectory to your project (This will add thespms::spms
target to your project).
Setup the memory for the ring buffer and the publisher
struct spms_config config = {0};
config.buf_length = 1024 * 1024; // buffer size
config.msg_entries = 1024; // max number of messages in the buffer
size_t needed_size = 0;
spms_ring_mem_needed_size(&config, &needed_size);
buffer = calloc(1, needed_size);
spms_pub *pub = NULL;
spms_pub_create(&pub, buffer, &config);
Write data to the ring
spms_pub_write_msg(pub, data, data_len, NULL);
Setup the subscriber
spms_sub *sub = NULL;
spms_sub_create(&sub, buffer);
Read data from the ring
uint8_t data[1024];
spms_sub_read_msg(sub, data, sizeof(data), NULL, 0);