pub struct EventBus { /* private fields */ }Expand description
Type-erased event bus for pub/sub communication.
The EventBus routes events to registered handlers based on event type.
It uses lock-free data structures for the hot dispatch path and
copy-on-write for subscription updates.
§Thread Safety
EventBus is Clone, Send, and Sync. Cloning creates a new handle
to the same underlying bus. Multiple threads can dispatch events
concurrently without blocking.
§Handler Ordering
Handlers are called in priority order (lower priority number = earlier). For handlers with the same priority, registration order is preserved.
§Two Usage Patterns
- Simple/Tests: Use
new()withemit_async()andprocess_queue() - Runtime: Use
new_with_channel()withsender()andtake_receiver()
Implementations§
Source§impl EventBus
impl EventBus
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new empty event bus.
This creates an EventBus without a channel. Use emit_async() and
process_queue() for deferred event processing.
For runtime integration with a dedicated processor thread, use
new_with_channel() instead.
Sourcepub fn new_with_channel(capacity: usize) -> Self
pub fn new_with_channel(capacity: usize) -> Self
Create an event bus with a channel for dedicated processor thread.
This is the preferred constructor for runtime integration where events
are processed by a dedicated OS thread using blocking_recv().
§Arguments
capacity- Bounded channel capacity (typically 1024)
§Usage Pattern
let bus = EventBus::new_with_channel(1024);
// Get sender for emitting events
let sender = bus.sender().unwrap();
// Take receiver for processor thread
let mut receiver = bus.take_receiver().unwrap();
// Spawn processor thread
std::thread::spawn(move || {
while let Some(event) = receiver.blocking_recv() {
// Process event
}
});
// Emit events from anywhere
sender.send(MyEvent { ... });Sourcepub fn sender(&self) -> Option<EventSender>
pub fn sender(&self) -> Option<EventSender>
Sourcepub fn take_receiver(&self) -> Option<BoundedReceiver<DynEvent>>
pub fn take_receiver(&self) -> Option<BoundedReceiver<DynEvent>>
Take the receiver for the dedicated processor thread.
Can only be called once. Subsequent calls return None.
§Example
let bus = EventBus::new_with_channel(1024);
let receiver = bus.take_receiver().expect("bus has channel");
// Spawn processor thread
std::thread::spawn(move || {
while let Some(event) = receiver.blocking_recv() {
// Process event
}
});Sourcepub fn subscribe<E, F>(&self, priority: u32, handler: F) -> Subscription
pub fn subscribe<E, F>(&self, priority: u32, handler: F) -> Subscription
Subscribe a handler for events of type E.
Returns a Subscription handle that unsubscribes when dropped.
§Arguments
priority- Handler priority (lower = called earlier). Convention:- 0-50: Core/critical handlers
- 100: Default priority
- 200+: Low priority (cleanup, logging)
handler- Function called for each event of typeE
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct MyEvent { value: i32 }
impl Event for MyEvent {}
let bus = EventBus::new();
let sub = bus.subscribe::<MyEvent, _>(100, |event| {
println!("Received: {:?}", event.value);
EventResult::Handled
});
// Handler is active while `sub` is alive
bus.emit(MyEvent { value: 42 });
// Dropping `sub` removes the handler
drop(sub);Sourcepub fn subscribe_with_context<E, F>(
&self,
priority: u32,
handler: F,
) -> Subscription
pub fn subscribe_with_context<E, F>( &self, priority: u32, handler: F, ) -> Subscription
Subscribe a context-aware handler for events of type E.
Similar to subscribe, but the handler receives a HandlerContext
that allows emitting new events, requesting renders, etc.
§Arguments
priority- Handler priority (lower = called earlier)handler- Function called for each event, with access to context
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct MyEvent { value: i32 }
impl Event for MyEvent {}
#[derive(Debug)]
struct FollowUpEvent;
impl Event for FollowUpEvent {}
let bus = EventBus::new();
let sub = bus.subscribe_with_context::<MyEvent, _>(100, |event, ctx| {
// Emit a follow-up event
ctx.emit(FollowUpEvent);
// Request render
ctx.request_render();
EventResult::Handled
});Sourcepub fn subscribe_targeted<E, F>(
&self,
target: &str,
priority: u32,
handler: F,
) -> Subscription
pub fn subscribe_targeted<E, F>( &self, target: &str, priority: u32, handler: F, ) -> Subscription
Subscribe a handler for targeted events, filtering by target.
The handler is only called when event.target() matches the
specified target string.
§Arguments
target- Target string to filter eventspriority- Handler priority (lower = called earlier)handler- Function called for matching events
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct PluginInput {
target: &'static str,
value: i32,
}
impl Event for PluginInput {}
impl TargetedEvent for PluginInput {
fn target(&self) -> &str { self.target }
}
let bus = EventBus::new();
// Only receives events where target == "my_plugin"
let sub = bus.subscribe_targeted::<PluginInput, _>("my_plugin", 100, |event, ctx| {
println!("My plugin received: {}", event.value);
EventResult::Handled
});Sourcepub fn emit<E: Event>(&self, event: E) -> EventResult
pub fn emit<E: Event>(&self, event: E) -> EventResult
Emit an event synchronously.
Dispatches the event to all registered handlers in priority order. Returns the combined result of all handlers.
§Handler Behavior
- Handlers are called in priority order (lower = first)
- If any handler returns
Consumed, dispatch stops - Otherwise continues until all handlers have been called
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct MyEvent;
impl Event for MyEvent {}
let bus = EventBus::new();
let result = bus.emit(MyEvent);
assert!(result.is_not_handled()); // No handlers registeredSourcepub fn emit_scoped<E: Event>(&self, event: E, scope: &EventScope) -> EventResult
pub fn emit_scoped<E: Event>(&self, event: E, scope: &EventScope) -> EventResult
Emit an event with scope tracking.
The scope’s counter is incremented before dispatch and decremented after all handlers complete. This allows callers to wait for all effects of the event to complete.
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct MyEvent;
impl Event for MyEvent {}
let bus = EventBus::new();
let scope = EventScope::new();
scope.increment(); // Manually increment before emit_scoped
let result = bus.emit_scoped(MyEvent, &scope);
// Scope counter is now decrementedSourcepub fn emit_async<E: Event>(&self, event: E)
pub fn emit_async<E: Event>(&self, event: E)
Queue an event for later processing.
The event is stored in an internal queue and processed when
process_queue() is called. This is useful for deferring
event dispatch to avoid reentrancy issues.
§Example
use reovim_kernel::api::v1::*;
#[derive(Debug)]
struct MyEvent;
impl Event for MyEvent {}
let bus = EventBus::new();
bus.emit_async(MyEvent);
bus.emit_async(MyEvent);
// Events are queued but not dispatched yet
let count = bus.process_queue();
assert_eq!(count, 2);Sourcepub fn emit_async_scoped<E: Event>(&self, event: E, scope: &EventScope)
pub fn emit_async_scoped<E: Event>(&self, event: E, scope: &EventScope)
Queue an event with scope tracking for later processing.
Like emit_async, but attaches a scope for lifecycle tracking.
The scope is incremented when queued and decremented after dispatch.
Sourcepub fn process_queue(&self) -> usize
pub fn process_queue(&self) -> usize
Process all queued events.
Drains the queue and dispatches each event synchronously. Returns the number of events processed.
§Scope Handling
For events with attached scopes, the scope is decremented after each event is dispatched.
Sourcepub fn dispatch(&self, event: &DynEvent) -> EventResult
pub fn dispatch(&self, event: &DynEvent) -> EventResult
Dispatch a type-erased event to registered handlers.
This is the core dispatch logic, used by both emit and process_queue.
Sourcepub fn dispatch_with_context(
&self,
event: &DynEvent,
ctx: &mut HandlerContext<'_>,
) -> DispatchResult
pub fn dispatch_with_context( &self, event: &DynEvent, ctx: &mut HandlerContext<'_>, ) -> DispatchResult
Dispatch an event with handler context.
This allows handlers to emit new events, request renders, etc.
Returns a DispatchResult containing the event result and any
side effects (emitted events, render requests).
§Example
let mut ctx = HandlerContext::new().with_scope(Some(scope));
let result = bus.dispatch_with_context(&event, &mut ctx);
if result.render_requested {
// Handle render request
}
// Process emitted events
for event in result.emitted_events {
bus.dispatch(&event);
}Sourcepub fn handler_count<E: Event>(&self) -> usize
pub fn handler_count<E: Event>(&self) -> usize
Get the number of handlers registered for a specific event type.
Useful for debugging and testing.
Sourcepub fn total_handler_count(&self) -> usize
pub fn total_handler_count(&self) -> usize
Get the total number of handlers registered across all event types.
Sourcepub fn queue_is_empty(&self) -> bool
pub fn queue_is_empty(&self) -> bool
Check if the async queue is empty.