simvx.core.event_bus

Typed event bus with weak handler references.

Handlers connect against a dataclass event type. Calling

meth:

EventBus.emit with an instance of that dataclass synchronously fans the event out to every live handler connected for the exact class. There is no MRO walk: a handler for Parent does NOT receive emits of Child(Parent) – subclasses must connect themselves. This keeps dispatch predictable and O(1) per event class.

Handlers are stored as weak references:

  • Bound methods are wrapped in :class:weakref.WeakMethod so the connection is automatically dropped when the owning instance is garbage collected.

  • Free functions and other callables are stored via :class:weakref.ref. CPython 3.13+ supports weakrefs to module-level functions, but local closures and functools.partial objects do not. Those raise

    class:

    TypeError at connect time – callers must use a method on a long-lived object, or hold their own strong reference and pass a module-level function.

Two dispatch modes:

  • meth:

    emit – synchronous. Handlers run in registration order on the calling thread before emit returns.

  • meth:

    emit_deferred – queues the event. The queue is drained when

    meth:

    flush_deferred is called (the SceneTree integration in C2 will call this once per frame).

Threading: the bus assumes a single-threaded engine. There are no locks. Calling emit from a non-main thread is undefined behaviour.

Module Contents

Classes

EventBus

Typed publish/subscribe bus keyed on dataclass event types.

Data

API

simvx.core.event_bus.EventCls

None

simvx.core.event_bus.Handler

None

class simvx.core.event_bus.EventBus[source]

Typed publish/subscribe bus keyed on dataclass event types.

Uses connect/disconnect to mirror :class:Signal vocabulary so both callback systems share one verb pair across the engine.

Initialization

__slots__

(‘_subs’, ‘_deferred’)

connect(event_cls: simvx.core.event_bus.EventCls, handler: simvx.core.event_bus.Handler) None[source]

Register handler for events of exactly event_cls.

Bound methods are stored via :class:weakref.WeakMethod. Other callables use :class:weakref.ref; if the callable does not support weak references (e.g. a local closure or

Class:

functools.partial), a :class:TypeError is raised.

disconnect(event_cls: simvx.core.event_bus.EventCls, handler: simvx.core.event_bus.Handler) None[source]

Remove handler from event_cls. Idempotent.

emit(event: Any) None[source]

Synchronously fan event out to handlers of its exact type.

Raises :class:TypeError if event is not a dataclass instance. Dead weak references are pruned lazily during iteration.

emit_deferred(event: Any) None[source]

Queue event for the next :meth:flush_deferred call.

flush_deferred() None[source]

Drain the deferred queue, dispatching each event via :meth:emit.