Waiting strategies
Pass a publisher strategy type and a consumer strategy type to EventBus.
Each must expose pub fn wait() void: a static, zero-argument function with no
receiver or error return. The bus does not create or pass a strategy instance.
It validates the strategy when forming the bus type.
waiting_strategy.BusySpin is the built-in strategy. Its wait()
returns immediately. Loops using it repeatedly poll, potentially occupying a
CPU core. Choose behavior according to your latency, CPU, and scheduling needs;
there is no universal fastest strategy.
A yielding strategy
Section titled “A yielding strategy”zig build example-waiting_strategyconst std = @import("std");const zigrupt = @import("zigrupt");
const Yield = struct { // A static zero-argument function, with no self pointer or error return. pub fn wait() void { std.Thread.yield() catch {}; }};comptime { zigrupt.waiting_strategy.validateWaitingStrategy(Yield);}
var count: usize = 0;fn handle(events: []const usize) usize { count += events.len; return events.len;}const Bus = zigrupt.EventBus(usize, false, &.{handle}, Yield, Yield);
pub fn main() !void { var bus = try Bus.init(std.heap.page_allocator, 8, 4); defer bus.deinit(); try bus.start(); errdefer bus.stop() catch {}; for (0..100) |value| try bus.produce(value); try bus.stop(); if (count != 100) return error.MissingEvents; std.debug.print("waiting_strategy: 100 events delivered using Yield\n", .{});}Yielding asks the scheduler to let another thread run, but does not guarantee a switch or a particular delay. Compare under representative workloads.
Where wait is called
Section titled “Where wait is called”The publisher strategy runs while a claimed slot cannot yet be reused.
The consumer strategy runs while startup is finishing and while a running
consumer is waiting for its next publication. It is not a callback after every
batch, and returning zero from a handler does not invoke it. The drain loop does
not use it to wait for missing publications, which is another reason producers
must complete before stop().
A strategy can be called concurrently by multiple producers or consumers. Any shared mutable strategy state requires synchronization; state specific to a thread can use appropriate thread-local storage. Strategies must eventually return so the bus can recheck progress. The current interface supplies no notification/wakeup registration, so indefinite parking requires coordination outside this API and can prevent progress.
