EntropyEngine::Core::EventBus
EntropyEngine::Core::EventBus
Section titled “EntropyEngine::Core::EventBus”Type-safe publish-subscribe event system for decoupled communication. More…
#include <EventBus.h>
Public Types
Section titled “Public Types”| Name | |
|---|---|
| using size_t | HandlerId |
| using std::function< void(const std::any &)> | EventHandler |
Public Functions
Section titled “Public Functions”| Name | |
|---|---|
| ~EventBus() =default | |
| template <typename EventType > bool | unsubscribe(HandlerId handlerId) Cancel your subscription - stop receiving these events. |
| template <typename EventType > HandlerId | subscribe(std::function< void(const EventType &)> handler) Sign up to receive a specific type of event - like subscribing to a newsletter. |
| template <typename EventType > void | publish(const EventType & event) Broadcast an event to all interested parties - fire and forget! |
| EventBus & | operator=(const EventBus & ) =delete |
| EventBus & | operator=(EventBus && ) =delete |
| bool | hasSubscribers() const Quick check if anyone is listening to anything at all. |
| size_t | getTotalSubscriptions() const Count total subscriptions across all event types. |
| template <typename EventType > size_t | getSubscriberCount() const Count how many subscribers are listening for a specific event type. |
| size_t | getMemoryUsage() const Estimate how much memory this EventBus is using. |
| void | clear() Nuclear option: remove all subscriptions for all event types. |
| EventBus() =default | |
| EventBus(const EventBus & ) =delete | |
| EventBus(EventBus && ) =delete |
Detailed Description
Section titled “Detailed Description”class EntropyEngine::Core::EventBus;Type-safe publish-subscribe event system for decoupled communication.
EventBus implements a publish-subscribe pattern where components can publish events and subscribe to specific event types without direct knowledge of each other. Publishers and subscribers only need to share common event type definitions.
Unlike traditional global event buses, this implementation is lightweight enough to support thousands of instances - one per WorkGraph, game entity, or UI widget. Memory usage remains manageable even with many instances.
Key features:
- Type-safe: Can’t accidentally subscribe to the wrong event type
- Thread-safe: Supports concurrent publishing from any thread
- Zero virtual functions: No vtable overhead
- Exception-safe: One bad handler won’t crash the whole system
- Self-cleaning: Removes empty handler lists when unsubscribing
Common use cases:
- Decoupling UI from game logic
- Progress notifications from long-running operations
- State change notifications in complex systems
- Any time you’re tempted to add Yet Another Callback Parameter
Complexity characteristics:
- Subscribe: O(1) amortized
- Publish: O(n) where n = subscribers for that event type
// Define your event types - just plain structsstruct PlayerHealthChanged { int oldHealth; int newHealth; bool isDead() const { return newHealth <= 0; }};
// Subscribe from anywhereEventBus& bus = gameEntity.getEventBus();auto healthId = bus.subscribe<PlayerHealthChanged>([this](const auto& e) { updateHealthBar(e.newHealth); if (e.isDead()) { showGameOverScreen(); }});
// Publish from anywhere elsebus.publish(PlayerHealthChanged{100, 0}); // RIP player
// Clean up when donebus.unsubscribe<PlayerHealthChanged>(healthId);Public Types Documentation
Section titled “Public Types Documentation”using HandlerId
Section titled “using HandlerId”using EntropyEngine::Core::EventBus::HandlerId = size_t;using EventHandler
Section titled “using EventHandler”using EntropyEngine::Core::EventBus::EventHandler = std::function<void(const std::any&)>;Public Functions Documentation
Section titled “Public Functions Documentation”function ~EventBus
Section titled “function ~EventBus”~EventBus() =defaultfunction unsubscribe
Section titled “function unsubscribe”template <typename EventType >inline bool unsubscribe( HandlerId handlerId)Cancel your subscription - stop receiving these events.
Parameters:
- handlerId The ID you got from subscribe()
Template Parameters:
- EventType The same event type you subscribed to
Return: true if successfully unsubscribed, false if ID wasn’t found
Pass the ID from subscribe() to remove handler. Cleans up empty lists. Thread-safe.
// Always save your subscription IDs!class GameUI { EventBus& bus; EventBus::HandlerId healthSubId;
void onEnable() { healthSubId = bus.subscribe<HealthChanged>([this](auto& e) { updateHealthBar(e.newHealth); }); }
void onDisable() { bus.unsubscribe<HealthChanged>(healthSubId); }};function subscribe
Section titled “function subscribe”template <typename EventType >inline HandlerId subscribe( std::function< void(const EventType &)> handler)Sign up to receive a specific type of event - like subscribing to a newsletter.
Parameters:
- handler Your callback - lambda, function, or callable
Template Parameters:
- EventType The event struct/class you want to receive
Return: A unique ID for this subscription (save it!)
Handler called for each published event. Returns ID for unsubscribing. Thread-safe.
// Simple lambda subscriptionauto id = bus.subscribe<MouseClick>([](const MouseClick& e) { std::cout << "Click at (" << e.x << ", " << e.y << ")\n";});
// Capture local stateint clickCount = 0;bus.subscribe<MouseClick>([&clickCount](const MouseClick& e) { clickCount++; if (clickCount >= 10) { unlockAchievement("ClickHappy"); }});
// Member function bindingbus.subscribe<GameStateChanged>( std::bind(&UIManager::onGameStateChanged, this, std::placeholders::_1));function publish
Section titled “function publish”template <typename EventType >inline void publish( const EventType & event)Broadcast an event to all interested parties - fire and forget!
Parameters:
- event The event data to send
Template Parameters:
- EventType The event type you’re publishing
Sends to all subscribers of this type. Handlers called synchronously. Safe: copies handlers, catches exceptions. Thread-safe.
// Fire a simple eventbus.publish(LevelCompleted{currentLevel, score, timeElapsed});
// Events can have methodsstruct DamageEvent { Entity* target; int amount; DamageType type;
bool isLethal() const { return target->health <= amount; }};
bus.publish(DamageEvent{player, 50, DamageType::Fire});
// Publishing to no subscribers is fine - nothing happensbus.publish(ObscureDebugEvent{}); // No subscribers? No problem!function operator=
Section titled “function operator=”EventBus & operator=( const EventBus &) =deletefunction operator=
Section titled “function operator=”EventBus & operator=( EventBus &&) =deletefunction hasSubscribers
Section titled “function hasSubscribers”inline bool hasSubscribers() constQuick check if anyone is listening to anything at all.
Return: true if any handlers are registered, false if completely empty
function getTotalSubscriptions
Section titled “function getTotalSubscriptions”inline size_t getTotalSubscriptions() constCount total subscriptions across all event types.
Return: Sum of all subscriptions for all event types
function getSubscriberCount
Section titled “function getSubscriberCount”template <typename EventType >inline size_t getSubscriberCount() constCount how many subscribers are listening for a specific event type.
Template Parameters:
- EventType The event type to check
Return: Number of active subscribers for this event type
Skip expensive work if nobody’s listening. Good for debugging too.
// Optimize expensive operationsif (bus.getSubscriberCount<DetailedPhysicsUpdate>() > 0) { // Only calculate detailed physics if someone cares auto details = calculateExpensivePhysicsDetails(); bus.publish(DetailedPhysicsUpdate{details});}function getMemoryUsage
Section titled “function getMemoryUsage”inline size_t getMemoryUsage() constEstimate how much memory this EventBus is using.
Return: Approximate bytes used by this EventBus
Includes object + dynamic allocations. Close enough for profiling.
// Memory profilingif (bus.getMemoryUsage() > 1024 * 1024) { // 1MB LOG_WARN("EventBus using {}KB of memory!", bus.getMemoryUsage() / 1024);}function clear
Section titled “function clear”inline void clear()Nuclear option: remove all subscriptions for all event types.
Wipes clean. All handler IDs become invalid. For shutdown cleanup. Thread-safe.
function EventBus
Section titled “function EventBus”EventBus() =defaultfunction EventBus
Section titled “function EventBus”EventBus( const EventBus &) =deletefunction EventBus
Section titled “function EventBus”EventBus( EventBus &&) =deleteUpdated on 2026-01-26 at 17:14:35 -0500