Squadrick / Shadesmar
Programming Languages
Projects that are alternatives of or similar to Shadesmar
Shadesmar
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.
Required packages: Msgpack
Caution: Pre-alpha software.
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.
-
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
Publisher:
#include <shadesmar/memory/copier.h>
#include <shadesmar/pubsub/publisher.h>
int main() {
shm::memory::DefaultCopier cpy;
shm::pubsub::Publisher pub("topic_name", &cpy);
const uint32_t data_size = 1024;
void *data = malloc(data_size);
for (int i = 0; i < 1000; ++i) {
p.publish(msg, data_size);
}
}
Subscriber:
#include <shadesmar/memory/copier.h>
#include <shadesmar/pubsub/subscriber.h>
void callback(shm::memory::Memblock *msg) {
// `msg->ptr` to access `data`
// `msg->size` to access `size`
// The memory will be free'd at the end of this callback.
// Copy to another memory location if you want to persist the data.
// Alternatively, if you want to avoid the copy, you can call
// `msg->no_delete()` which prevents the memory from being deleted
// at the end of the callback.
}
int main() {
shm::memory::DefaultCopier cpy;
shm::pubsub::Subscriber sub("topic_name", &cpy, callback);
// Using `spinOnce` with a manual loop
while(true) {
sub.spin_once();
}
// OR
// Using `spin`
sub.spin();
}
Publish-Subscribe (serialized messages)
For plug-and-play convenience Shadesmar supports msgpack serialization.
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;
};
class CustomMessage : public shm::BaseMsg {
public:
int val{};
std::vector<int> arr;
InnerMessage im;
SHM_PACK(val, arr, im);
explicit CustomMessage(int n) {
val = n;
for (int i = 0; i < 1000; ++i) {
arr.push_back(val);
}
}
// MUST BE INCLUDED
CustomMessage() = default;
};
Publisher:
#include <shadesmar/pubsub/serialized_publisher.h>
#include <custom_message.h>
int main() {
shm::pubsub::SerializedPublisher<CustomMessage> pub("topic_name");
CustomMessage msg;
msg.val = 0;
for (int i = 0; i < 1000; ++i) {
p.publish(msg);
msg.val++;
}
}
Subscriber:
#include <iostream>
#include <shadesmar/pubsub/serialized_subscriber.h>
#include <custom_message.h>
void callback(const std::shared_ptr<CustomMessage>& msg) {
std::cout << msg->val << std::endl;
}
int main() {
shm::pubsub::SerializedSubscriber<CustomMessage> sub("topic_name", callback);
// Using `spinOnce` with a manual loop
while(true) {
sub.spin_once();
}
// OR
// Using `spin`
sub.spin();
}
RPC (Currently broken)
Server:
#include <shadesmar/rpc/server.h>
int add(int a, int b) {
return a + b;
}
int main() {
shm::rpc::Function<int(int, int)> rpc_fn("add_fn", add);
while (true) {
rpc_fn.serve_once();
}
// OR...
rpc_fn.serve();
}
Client:
#include <shadesmar/rpc/client.h>
int main() {
shm::rpc::FunctionCaller rpc_fn("add_fn");
std::cout << rpc_fn(4, 5).as<int>() << std::endl;
}