24#include <unordered_map>
66 using VectorNode = std::vector<INode *>;
254 template<
class T,
class... Args>
255 bool emit(Args &&...args);
270 bool post(
const std::shared_ptr<Message> &message)
const;
281 size_t postMessageToSubscribers(
MessageTypeID eventType,
const std::shared_ptr<Message> &message)
const;
288 size_t postMessageToBroadcastSubscribers(
const std::shared_ptr<Message> &message)
const;
295 const VectorNode *getSubscribersForMessageType(
MessageTypeID messageType)
const;
304 std::unordered_map<MessageTypeID, VectorNode>
nodeList;
315 m_busStartTimestamp = std::chrono::steady_clock::now();
321 std::scoped_lock lock(m_routingTable.mtx);
323 m_routingTable.nodeList.clear();
324 m_routingTable.broadcastNodeList.clear();
332 throw std::runtime_error(
"invalid node handle");
334 std::scoped_lock lock(m_routingTable.mtx);
336 if (!m_routingTable.nodeList.contains(eventType))
338 m_routingTable.nodeList[eventType] = { node };
342 auto &nodes = m_routingTable.nodeList.at(eventType);
343 if (std::ranges::find(nodes, node) == nodes.end())
346 nodes.push_back(node);
356 throw std::runtime_error(
"invalid node handle");
358 std::scoped_lock lock(m_routingTable.mtx);
361 if (!m_routingTable.nodeList.contains(eventType))
365 auto &nodes = m_routingTable.nodeList.at(eventType);
366 std::erase(nodes, node);
374 throw std::runtime_error(
"invalid node handle");
376 std::scoped_lock lock(m_routingTable.mtx);
379 for (
auto &
nodeList : m_routingTable.nodeList | std::views::values)
383 m_routingTable.broadcastNodeList.erase(node);
391 throw std::runtime_error(
"invalid node handle");
393 std::scoped_lock lock(m_routingTable.mtx);
396 if (!m_routingTable.nodeList.contains(eventType))
400 const auto &nodes = m_routingTable.nodeList.at(eventType);
401 return std::ranges::find(nodes, node) != nodes.end();
409 throw std::runtime_error(
"invalid node handle");
411 std::scoped_lock lock(m_routingTable.mtx);
414 m_routingTable.broadcastNodeList.insert(node);
422 throw std::runtime_error(
"invalid node handle");
424 std::scoped_lock lock(m_routingTable.mtx);
427 m_routingTable.broadcastNodeList.erase(node);
435 throw std::runtime_error(
"invalid node handle");
437 std::scoped_lock lock(m_routingTable.mtx);
440 return m_routingTable.broadcastNodeList.contains(node);
444template<
class T,
class... Args>
447 static_assert(std::derived_from<T, Message>,
"T must be derived from IMessage");
450 auto message = std::make_shared<T>(std::forward<Args>(args)...);
453 return post(message);
457inline bool Bus::post(
const std::shared_ptr<Message> &message)
const
459 std::scoped_lock lock(m_routingTable.mtx);
462 message->updateTimestamp();
467 const auto subscriberCount = postMessageToSubscribers(message->getMessageTypeID(), message);
472 (void)postMessageToBroadcastSubscribers(message);
474 return subscriberCount > 0;
478inline size_t Bus::postMessageToSubscribers(
const MessageTypeID eventType,
const std::shared_ptr<Message> &message)
const
480 const auto subscriberList = getSubscribersForMessageType(eventType);
484 for (
const auto &node : *subscriberList)
485 node->append(message);
487 return subscriberList->size();
491inline size_t Bus::postMessageToBroadcastSubscribers(
const std::shared_ptr<Message> &message)
const
494 node->append(message);
496 return m_routingTable.broadcastNodeList.size();
500inline const Bus::VectorNode *Bus::getSubscribersForMessageType(
const MessageTypeID messageType)
const
502 if (!m_routingTable.nodeList.contains(messageType))
505 return &m_routingTable.nodeList.at(messageType);