Goal
Use the event bus to decouple publishers from subscribers. You'll learn how to define events, subscribe handlers, and publish without the publisher knowing who — if anyone — is listening.
Prerequisites
Step 1: Define an event type
Events are plain structs. Keep them immutable — subscribers should not modify the event they receive.
std::string user_id;
std::chrono::system_clock::time_point timestamp;
};
Event bus abstraction and common events.
Step 2: Subscribe a handler
Subscribers register a callback for a specific event type. The handle returned by subscribe must stay alive for as long as you want the subscription active — destroying it cancels the subscription.
class audit_logger {
event_bus::subscription sub_;
public:
std::cout << "AUDIT: " << event.user_id
<< " logged in" << std::endl;
});
}
};
Simple synchronous event bus for testing when monitoring is disabled.
uint64_t subscribe(HandlerFunc &&func)
Subscribe to events of a specific type.
Generic event structure for the event bus.
Step 3: Publish from another component
The publisher holds no reference to subscribers — it just fires the event. All subscribers registered for that type receive it.
class authentication_service {
public:
explicit authentication_service(
event_bus& bus) : bus_(bus) {}
auto session = verify_credentials(creds);
if (session.is_error()) return session;
.user_id = creds.username,
.timestamp = std::chrono::system_clock::now()
});
return session;
}
};
Result type for error handling with member function support.
void publish(const EventType &evt, event_priority=event_priority::normal)
Publish an event to all subscribed handlers.
Common Mistakes
- Long-running handlers. Handlers run on the publisher's thread by default. If you need to do heavy work, hand off to a worker thread — otherwise the publisher is blocked.
- Subscribing inside handlers. Adding/removing subscriptions while dispatching an event can cause invalidation. Defer such changes to after the handler returns.
- Forgetting to store the subscription. A discarded subscription handle is immediately cancelled. Keep it in a member variable or container.
Next Steps
- FAQ — when to use event bus vs direct method calls
- Troubleshooting — debugging missing events