Class EventBus

Nested Relationships

Nested Types

Class Documentation

class EventBus

Declaration: final

An owned named-event registry.

A bus separates registrations/lifecycle; it does not select a thread. Immediate dispatch runs on its producer’s thread. String/any payload consistency remains the application author’s contract. Typed channels isolate name/type identity and check payloads before callback entry, using the same persistent registration and optional delivery lifetime.

Public Types

using Callback = std::function<void(std::any)>

Legacy named-event callback receiving an owned std::any payload copy; its type agreement belongs to callers.

using Work = std::move_only_function<void()>

Move-only deferred task whose ownership transfers only when Delivery accepts it.

using Delivery = std::function<bool(Work)>

Deferred FIFO-per-listener transport: return true only after owning work; rejection returns false or throws without retaining it.

Never invoke inline or block waiting.

using ErrorHandler = std::function<void(std::exception_ptr)>

Required queued-error sink; must not throw and must protect captures through pending-task destruction independently of listener invalidation.

Public Functions

inline Publisher publisher() const noexcept

Declaration: [[nodiscard]]

Borrow notification access without retaining this bus; obtain while the bus is alive.

EventBus() = default

Create an open independently owned registry; immediate delivery is the default.

See also

Detailed guide

~EventBus()

Close invocation gates and release registry ownership.

Does not wait for running callbacks; settle producers and retained callback dependencies before destroying them.

See also

Detailed guide

EventBus(const EventBus&) = delete

Copying a registry is disabled; compose independent owned buses explicitly.

See also

Detailed guide

EventBus &operator=(const EventBus&) = delete

Registry ownership cannot be copied through assignment.

See also

Detailed guide

Registration register_listener(const std::string &event, Callback callback, Delivery delivery = Delivery{}, ErrorHandler errors = ErrorHandler{})

Register a persistent listener on an exact legacy name.

See also

Detailed guide

Parameters:
  • event – Name owned after registration; empty names are permitted.

  • callback – Owned callable receiving a copied std::any; nonempty required.

  • delivery – Optional owned deferred transport; absent invokes immediately on the producer thread.

  • errors – Required nonthrowing error sink when delivery is supplied; owns/protects its captured dependencies.

Throws:
  • CE::Exceptions::invalid_args – For an empty callback or queued delivery without an error sink.

  • CE::Exceptions::failed_operation – For a closed bus or exhausted registration IDs. Registry operations are synchronized; callbacks run outside registry locks and may reenter. Payload agreement remains application-owned.

Returns:

Bus-qualified non-owning identifier; discarding it does not unsubscribe.

void dispatch(const std::string &event, const std::any &payload)

Dispatch a legacy named payload to the registration snapshot.

See also

Detailed guide

Parameters:
  • event – Exact legacy channel name, separate from typed channels.

  • payload – Borrowed for this call and copied for listeners/deferred ownership. A closed bus rejects. Immediate callback exceptions propagate to the producer; deferred preparation/submission/callback failures and loss of still-active work reach the listener’s error sink. Explicit unregister/close instead discards pending delivery without reporting cancellation. Concurrent invalidation prevents new callback entry even for an already captured registration snapshot.

template<::CE::Events::EventPayload Payload>
inline Registration register_listener(const ::CE::Events::EventChannel<Payload> &event, typename ::CE::Events::EventChannel<Payload>::Callback callback, Delivery delivery = Delivery{}, ErrorHandler errors = ErrorHandler{})

Register a typed listener on an exact name/type channel.

See also

Detailed guide

Template Parameters:

Payload – Unqualified copy-constructible object type.

Parameters:
  • event – Channel value; its name/type are retained, not the EventChannel object.

  • callback – Nonempty owned callable borrowing an invocation-owned payload copy.

  • delivery – Optional deferred FIFO transport with the same rules as named registration.

  • errors – Nonthrowing sink required for deferred delivery.

Returns:

Persistent non-owning registration ID. Validation, closure, unsubscription and queued lifetime match the named overload. Different payload types or the legacy named channel remain isolated.

template<::CE::Events::EventPayload Payload, typename Value>
inline void dispatch(const ::CE::Events::EventChannel<Payload> &event, Value &&payload)

Requires: std::same_as<std::remove_cvref_t<Value>, Payload> && std::is_constructible_v<Payload, Value&&>

Own an exact-type payload before dispatching its typed channel.

See also

Detailed guide

Template Parameters:
  • Payload – Declared channel payload.

  • Value – Must have exactly Payload as its unqualified type and construct Payload from the forwarded value.

Parameters:
  • event – Exact name/type channel.

  • payload – Value copied or moved into owned storage before callbacks. Construction failures reach the producer. Immediate callback exceptions propagate; deferred failures use the listener error sink. No implicit conversion to another payload type/channel occurs.

template<::CE::Events::EventPayload Payload, typename Value>
inline void notify(const ::CE::Events::EventChannel<Payload> &event, Value &&payload, const ErrorHandler &errors = ErrorHandler{}) noexcept

Requires: std::same_as<std::remove_cvref_t<Value>, Payload> && std::is_constructible_v<Payload, Value&&>

Attempt typed observation delivery without propagating notification failures.

Parameters:
  • event – Exact name/type channel; legacy named listeners are separate.

  • payload – Exact-type value copied/moved into owned delivery storage.

  • errors – Optional synchronous sink for payload preparation, closed-bus, snapshot and immediate-listener failures. The sink runs outside bus locks and must not recursively notify through this bus. An empty or throwing sink uses independent emergency reporting. Each immediate listener is attempted despite earlier failures. Queued listeners retain their registration-owned error sinks and delivery lifetimes. Invalidation still prevents invocation entry. Nested notification remains synchronous; source ordering/coalescing belongs to the producer.

bool unregister_listener(const Registration &registration)

Invalidate a listener before removing it from the registry.

See also

Detailed guide

Parameters:

registration – Non-owning identifier; foreign/expired/empty values do not remove another listener.

Returns:

True only when the listener was removed from this bus. Prevents new invocation entry; callbacks already running continue. This does not wait or require pending tasks to be destroyed.

void wait_for_listener(const Registration &registration) const

Wait only for running invocations of an already invalidated listener.

See also

Detailed guide

Parameters:

registration – Identifier originating from this bus.

Throws:
  • CE::Exceptions::invalid_args – For a foreign/empty registration.

  • CE::Exceptions::failed_operation – If still active or waiting from that listener’s own nested invocation. An expired listener returns immediately. Pending deferred task/capture destruction is independent; do not block a thread needed by running callbacks.

bool unregister_and_wait(const Registration &registration)

Invalidate/remove, then wait for running callback entries to finish.

See also

Detailed guide

Returns:

Whether unregister_listener() removed the listener. The same foreign/self-wait errors as wait_for_listener() apply. This is not a barrier for destruction of all queued transport captures.

void close()

Idempotently close every invocation gate and reject new registration/dispatch.

All concurrent close calls return with gates invalidated. Running callbacks keep their invocation ownership and are not waited for; captured dependencies must remain protected.

See also

Detailed guide

::CE::Events::EventStats diagnostics() const

Declaration: [[nodiscard]]

Copy synchronized registry counts and independently sampled cumulative counters.

See also

Detailed guide

Returns:

Owned observations, not a callback-completion or transport-destruction barrier.

void report_diagnostics() const noexcept

Emit an explicit unlocked registry summary without payload/name sampling.

Call outside registry edits, native callbacks and sensitive destruction paths. Reporting failures use the emergency path.

See also

Detailed guide