My Final Project
I built a C++ inter-process communication library that uses shared memory for sending messages between processes. It currently supports publish-subscribe and RPC paradigms. Since it uses shared memory, the library is blazing fast and allows for zero-copy transfers.
Demo Link
You can check out the examples here. For a demo of it in action, you can see the GitHub Actions CI of the project.
Link to Code
Fast C++ IPC using shared memory (with msgpack)
Shadesmar
Soulcast hoid pointers.
An IPC library that uses the system's shared memory to pass messages
The communication paradigm is either publish-subscibe or RPC similar to ROS and ROS2
The library was built to be used within Project MANAS.
Required packages: Boost, Msgpack
Features
-
Multiple subscribers and publishers.
-
Multithreaded RPC support.
-
Uses a circular buffer to pass messages between processes.
-
Faster than using the network stack like in the case with ROS.
-
Read and write directly from GPU memory to shared memory.
-
Decentralized, without resource starvation.
-
Allows for both serialized message passing (using msgpack
) and to
pass raw bytes.
-
No need to define external IDL files for messages. Use C++ classes as
message definition.
Publish-Subscribe (serialized messages)
Message Definition (custom_message.h
):
#include <shadesmar/message.h>
class InnerMessage : public shm::BaseMsg {
public:
int inner_val{}
std::string inner_str{};
SHM_PACK(inner_val, inner_str);
InnerMessage() = default;
…
How I built it (what's the stack? did I run into issues or discover something new along the way?)
The library is built entirely in C++17. I use msgpack for serializing C++ objects to transfer them "over-the-wire", but this is not a necessity. For higher performance, the library allows transferring memory directly (pointers).
At the core of the library is a SharedQueue
which is a circular MPMC queue that runs entirely in shared memory space. It is built with the intention to minimize contention as much as possible, with all writes to the queue being lock-free. There is currently work underway to make the queue fully lock-free.
The SharedQueue
indexes into the underlying shared memory buffer that uses Boost's managed_shared_memory
for maintaining allocations, using a red-black tree.
The library also supports inter-device transfers (CPU->GPU, etc.) using a new construct called Copier
. This also allows for exotic copy functions apart from std::memcpy
.
I faced several challenges while building Shadesmar, chief among them being the need for robust interprocess locks. I found little to no pre-existing information so I decided to write a few blog posts on my website:
- Interprocess Locks
-
(Better) Interprocess Locks
Writing the tests for the library was particularly tricky since all tests needed to fork()
for inter-process communication, and all the testing frameworks I tried don't seem to work when using fork()
. I'm currently manually doing tests with assert
s.
Additional Thoughts / Feelings / Stories
The name of the library is from one of my favourite high fantasy novels: The Stormlight Archive by Brandon Sanderson. In the books, Shadesmar is an alternative plane of existence that binds the other two planes of existence together. I used the name since shared memory (shm) is the bridge between processes.
Funnily enough, I recently posted about my library on Reddit and was acknowledged by the author.