added a simple message bus
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#include "matador/utils/message_bus.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
message::message()
|
||||
: ptr_(nullptr)
|
||||
, owner_(nullptr)
|
||||
, type_(typeid(void)) {}
|
||||
|
||||
bool message::empty() const {
|
||||
return ptr_ == nullptr && !owner_;
|
||||
}
|
||||
|
||||
std::type_index message::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
const void * message::msg_ptr() const {
|
||||
return owner_ ? owner_.get() : ptr_;
|
||||
}
|
||||
|
||||
subscription::subscription(message_bus *bus, const std::type_index type, const uint64_t id)
|
||||
: bus_(bus)
|
||||
, type_(type)
|
||||
, id_(id) {}
|
||||
|
||||
subscription::subscription(subscription &&other) noexcept
|
||||
: bus_(other.bus_)
|
||||
, type_(other.type_)
|
||||
, id_(other.id_) {
|
||||
other.bus_ = nullptr;
|
||||
}
|
||||
|
||||
subscription& subscription::operator=(subscription &&other) noexcept {
|
||||
if (this != &other) {
|
||||
unsubscribe();
|
||||
bus_ = other.bus_;
|
||||
type_ = other.type_;
|
||||
id_ = other.id_;
|
||||
other.bus_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
subscription::~subscription() {
|
||||
unsubscribe();
|
||||
}
|
||||
|
||||
bool subscription::valid() const {
|
||||
return bus_ != nullptr;
|
||||
}
|
||||
|
||||
void message_bus::unsubscribe(const std::type_index type, HandlerId id) {
|
||||
std::unique_lock writeLock(mutex_);
|
||||
const auto it = handlers_.find(type);
|
||||
if (it == handlers_.end()) {
|
||||
return;
|
||||
}
|
||||
auto &handler_vector = it->second;
|
||||
handler_vector.erase(std::remove_if(handler_vector.begin(), handler_vector.end(),
|
||||
[id](const Entry &e) { return e.id == id; }),
|
||||
handler_vector.end());
|
||||
if (handler_vector.empty()) {
|
||||
handlers_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void message_bus::unsubscribe(HandlerId id) {
|
||||
std::unique_lock writeLock(mutex_);
|
||||
for (auto it = handlers_.begin(); it != handlers_.end(); ) {
|
||||
auto &handler_vector = it->second;
|
||||
handler_vector.erase(std::remove_if(handler_vector.begin(), handler_vector.end(),
|
||||
[id](const Entry &e) { return e.id == id; }),
|
||||
handler_vector.end());
|
||||
if (handler_vector.empty()) it = handlers_.erase(it);
|
||||
else ++it;
|
||||
}
|
||||
}
|
||||
|
||||
void message_bus::publish(const message &msg) const {
|
||||
if (msg.empty()) {
|
||||
return;
|
||||
}
|
||||
std::vector<Entry> snapshot;
|
||||
{
|
||||
std::shared_lock readLock(mutex_);
|
||||
const auto it = handlers_.find(msg.type());
|
||||
if (it == handlers_.end()) {
|
||||
return;
|
||||
}
|
||||
snapshot = it->second;
|
||||
}
|
||||
const void* p = msg.msg_ptr();
|
||||
for (const auto &e : snapshot) {
|
||||
if (!e.filter || e.filter(p)) e.handler(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user