Event System
Usage Notes
See Events in Erbsland Core for the programming model and scheduling examples, and Running an Application with Event Loops for application and worker-loop designs.
Events::post accepts raw event objects; invoke queues callbacks, and invokeAfter queues delayed callbacks.
EventTimer supplies cancellation and repetition through a retained handle.
See Scheduling Work and Timers for delay, timer lifetime, repetition, and debounce, and
Building Workflows Across Callbacks for coordinating operation state, dependent steps, and completion.
For request/reply ownership across threads, see Communicating Between Event Loops.
For resource completion before loop termination and thread joins, see Cancelling Work and Shutting Down.
currentEvents() identifies the loop currently running on the calling thread.
EventLoopDriver provides the native wait and wake interface for custom reactors and tests.
Bound Callbacks
bindEvent() creates a reusable callback that queues its handler on a captured
EventsPtr.
Supply an explicit target, or omit it to capture currentEvents() when
creating the binding.
The returned object has an implementation-defined type, can be stored with auto, and converts to compatible
std::function<void(...)> callback parameters.
The handler must return void and be callable as an lvalue.
Free functions, function objects, generic lambdas, and move-only captures are supported.
auto completed = el::bindEvent(target, [](el::String result) -> void {
el::io::printLine(result);
});
// Any producer thread can submit arguments; the target loop executes the handler.
completed("Finished"_el);
The member-function overload takes a shared recipient and a member-function pointer.
It supports inherited, const, and noexcept methods where the supplied recipient and arguments are compatible.
An implicit target must be captured while the intended receiving loop is running on the calling thread:
// Inside a Workflow method running on its receiving loop:
scanner.scan(el::bindEvent(shared_from_this(), &Workflow::onScanned));
bindWeakEvent() accepts a weak recipient and a member-function pointer.
It queues each invocation, then locks the recipient immediately before dispatching the method on the receiving loop.
An empty or expired recipient suppresses the method call; a successful lock retains the recipient until the method
returns or throws.
scanner.scan(el::bindWeakEvent(weak_from_this(), &Workflow::onScanned));
Arguments and Handler State
Binding queues no work. Every call to the returned callback creates an independent delivery, including calls made on the receiving loop itself. There is no inline execution, synchronous result, or cancellation handle. Sequential submissions retain the target’s queue order; concurrent producers have no additional ordering guarantee.
Arguments are stored using their decayed types: lvalues are copied and rvalues are moved.
Dispatch passes the stored arguments as rvalues, supporting value, const-reference, and rvalue-reference parameters.
A non-const reference parameter requires an explicit std::ref or std::reference_wrapper argument.
Pointers, views, and reference wrappers still borrow their referents; copying them does not copy the underlying data.
The caller must keep that data alive and synchronize any shared access.
Conversions to handler parameter types occur during dispatch, after storing the supplied argument types.
Copies of a binding, including copies stored in std::function, share one handler and its mutable state.
Move-only captures remain in that shared handler and are not consumed by delivery.
Only the receiving loop invokes the handler; simultaneous submissions through a stable binding or its copies are safe.
Concurrent assignment or destruction of the same binding object requires caller synchronization.
Moved-from bindings may be destroyed or reassigned; calling one throws LogicFailure.
Lifetime and Failure
A binding retains its target, but does not start the loop, keep its thread running, or guarantee acceptance or delivery. Strong member bindings retain their recipient while any binding copy or queued delivery exists. Weak bindings never retain the recipient during submission. An expired weak recipient still consumes a queue entry until dispatch, and does not report completion to its producer.
Destroying the binding does not cancel submitted work. Queued transport retains the handler and arguments without retaining the target through the binding itself. Captures supplied by the caller can still create ownership cycles. Destruction of handlers, arguments, and recipients has no thread-affinity guarantee: final ownership can be released by dispatch, rejection, target destruction, or destruction of the last binding copy.
Null explicit targets, null strong recipients, null function or member pointers, and empty std::function handlers
produce ParameterFailure during binding.
Implicit binding outside a running loop produces LogicFailure through currentEvents().
Incompatible invocation arguments and non-void handler results are rejected at compile time when checking or using the
returned callable.
An overloaded method name must first be resolved to the intended member-function pointer type by the caller.
Handler construction, allocation, argument-storage, and submission exceptions propagate on the calling thread.
Argument storage completes before submission; if it fails, no delivery is queued, although supplied rvalues may already
have been moved from.
Exceptions from handler execution follow the receiving loop’s error policy.
Queue capacity, blocking, and shutdown follow the existing invoke() contracts described in
Queue Capacity and Error Policies; a returned invocation does not establish that the handler ran or will run.
Event Thread Lifecycle
Event threads are one-shot objects.
After start() succeeds, isStarted() remains true even after the worker terminates and is joined.
isRunning() only observes whether the event loop is currently executing and is not a synchronization barrier for
startup or completion.
quit() is an idempotent asynchronous request.
It can be issued before startup and lets events queued before the quit request run before the loop terminates.
join() is only a wait operation: it never requests termination, is a no-op before startup or after a previous join,
and must not be called from the event thread itself.
It does not transport exceptions from the worker thread; an exception that escapes the event loop terminates the
process.
Destroying an event thread requests termination and joins a started worker. Therefore, the final owning pointer must be released from another thread, never from the event thread itself.
Queue Capacity and Error Policies
For practical policy choices and completion paths, see Handling Event Failures and Keeping Event Loops Responsive Under Load.
EventLoopOptions is a fluent value copied when a loop or thread is created.
Pass it to Application::createEventThread(options), UnmanagedEventThread::create(options), or any
EventLoop::create overload; driver and backend overloads take options last.
The default queue is unlimited and callback failures are stored while dispatch continues.
maximumQueuedEvents() limits ordinary waiting events; zero means unlimited.
queuedEventCount() returns a synchronized snapshot of ordinary and reserved waiting events.
The executing callback, delayed scheduler callbacks, timers not yet queued, and reserved quit control are excluded.
This limits event count, not payload bytes, blocked producers’ retained events, or the stored error queue.
Ordinary due callbacks become subject to capacity when the scheduler posts them.
Checking the count before posting cannot enforce capacity; admission itself performs the atomic check.
Background-operation completions and selected deadlines use separately reserved queue capacity, with at most 1,024 live
reservations per loop.
These callbacks count toward queuedEventCount() but do not consume the ordinary queue limit.
Ordinary and reserved callbacks alternate when both queues contain work.
An operation that cannot reserve its continuation capacity is rejected before it starts.
Shutdown discards pending completions and their retained resources; it does not run callbacks on a worker thread or wait
for an uninterruptible native call.
When capacity is reached, queueOverflowAction() selects one of these behaviors:
Terminatecallsstd::terminate(). This is the default overflow action.FailApplicationrejects the incoming event and reportsEventQueueFullErrorto the owning application.Quitrejects the incoming event, closes admission, and drains accepted work.Blockwaits for space; when the active consumer itself would wait, it callsstd::terminate().Ignorediscards the incoming event and preserves the accepted queue.
Blocking requires another thread to run or drain the loop, including before a worker starts. Stop and quit wake blocked producers, which discard their pending events. They cannot interrupt a callback that is blocked; joins still wait for that callback to return. Quit control bypasses capacity and does not appear in the queue count. Rejected repeating timer occurrences are skipped and rescheduled while admission remains open.
errorPolicy() controls RuntimeError exceptions from invocation and backend event dispatch when no custom error
handler is installed:
Ignorediscards the exception and continues.Storeretains the exception forhasError()andtakeError()and continues.Quitstores the exception, closes admission, and drains accepted events.FailApplicationstores the exception and forwards it to the owning application.
A custom setErrorHandler() replaces the default action; the exception is still stored before the handler runs.
Clearing the handler restores the configured default policy.
A handler throwing RuntimeError adds its own exception and stops the loop.
Programming errors, allocation failures, thread-resource exhaustion, and other exceptions bypass these policies and
handlers.
They propagate unchanged from a directly run loop and terminate an event worker if they escape its thread entry point.
Fatal failures in a custom error handler also terminate, because error handling cannot propagate.
Applications must use RuntimeError subclasses for operational callback failures that the loop should handle.
Queue overflow is governed independently and does not invoke the callback-error handler.
FailApplication is available only on application-managed workers.
Standalone loop and unmanaged-thread factories reject options selecting it with ParameterFailure.
Managed failures preserve the first application error, stop normal main-loop dispatch, and request graceful shutdown of
every managed event thread.
This also releases a procedural main that is waiting for a separate receiver thread to finish.
The retained failure is rethrown on the application thread after shutdown processing and worker joins.
This includes errors arriving before main-loop startup or while workers are being joined.
These runtime exceptions follow the application’s diagnostic and exit-code handling.
If a worker outlives its application state, its failure is retained locally and its loop quits.
Source Editors and Subscriptions
An EventSource owns its handlers and one stable EventEditor returned by reference.
Editor access and handler changes belong on the source’s owner loop.
An on...() method replaces one handler; an empty callback clears it.
EventEditor::source() and target() return owning pointers, while the editor itself remains borrowed.
On applications, parts, and event threads, events() instead returns an EventsPtr target.
See Connecting to Event Sources for setup, frontend access, and callback argument contracts.
Multiple-observer notifications use add...() and return move-only EventSubscription handles.
Retain each handle to keep its registration active; cancellation or destruction prevents future invocations, while an
already started callback may finish.
Publisher destruction invalidates its registrations.
A notification uses either single-handler or observer semantics.
See Keeping Callbacks and Their Owners Alive for ownership, weak captures, cancellation, and safe callback cleanup.
Default native-driver creation, native event registration, and failed waits raise PlatformError with the captured
POSIX or Windows error context.
Wait failures propagate from run(), runOnce(), and runUntilIdle(); they are not callback failures governed
by errorPolicy().
Interface
-
template<typename tFunction>
auto erbsland::event::bindEvent(EventsPtr events, tFunction &&callback) Bind a callback to an explicit event target.
- Template Parameters:
tFunction – The handler type; invocations must return void.
- Parameters:
events – The non-null target on which the handler will execute.
callback – The handler to copy or move into shared storage. Function pointers and
std::functionobjects must not be empty.
- Throws:
Any – exception from allocating or constructing the handler.
See: Bound Callbacks
- Returns:
A copyable callable that queues owned arguments; copies share the handler.
-
template<typename tFunction>
auto erbsland::event::bindEvent(tFunction &&callback) Bind a callback to the event loop currently running on this thread.
The calling thread must be running an event loop.
- Template Parameters:
tFunction – The handler type; invocations must return void.
- Parameters:
callback – The handler to copy or move into shared storage. Function pointers and
std::functionobjects must not be empty.- Throws:
Any – exception from allocating or constructing the handler.
See: Bound Callbacks
- Returns:
A copyable callable retaining the current target and sharing its handler with copies.
Bind a retained recipient’s method to an explicit event target.
- Template Parameters:
tRecipient – The recipient type, optionally const or derived from the method’s class.
tMethod – The member-function pointer type; invocations must return void.
- Parameters:
events – The non-null target on which the method will execute.
recipient – The non-null recipient retained by bindings and queued deliveries.
method – The non-null member-function pointer.
- Throws:
Any – exception from allocating the shared handler.
See: Bound Callbacks
- Returns:
A copyable callable that queues owned arguments for the retained recipient.
Bind a retained recipient’s method to the current event loop.
The calling thread must be running an event loop.
- Template Parameters:
tRecipient – The recipient type, optionally const or derived from the method’s class.
tMethod – The member-function pointer type; invocations must return void.
- Parameters:
recipient – The non-null recipient retained by bindings and queued deliveries.
method – The non-null member-function pointer.
- Throws:
Any – exception from allocating the shared handler.
See: Bound Callbacks
- Returns:
A copyable callable retaining the current target and the recipient.
-
template<typename tRecipient, typename tMethod>
auto erbsland::event::bindWeakEvent(EventsPtr events, std::weak_ptr<tRecipient> weakRecipient, tMethod method) Bind a weak recipient’s method to an explicit event target.
- Template Parameters:
tRecipient – The recipient type, optionally const or derived from the method’s class.
tMethod – The member-function pointer type; invocations must return void.
- Parameters:
events – The non-null target on which the method will execute.
weakRecipient – The recipient to lock during dispatch; empty and expired pointers are allowed.
method – The non-null member-function pointer.
- Throws:
Any – exception from allocating the shared handler.
See: Bound Callbacks
- Returns:
A copyable callable that queues owned arguments and skips expired recipients at dispatch.
-
template<typename tRecipient, typename tMethod>
auto erbsland::event::bindWeakEvent(std::weak_ptr<tRecipient> weakRecipient, tMethod method) Bind a weak recipient’s method to the current event loop.
The calling thread must be running an event loop.
- Template Parameters:
tRecipient – The recipient type, optionally const or derived from the method’s class.
tMethod – The member-function pointer type; invocations must return void.
- Parameters:
weakRecipient – The recipient to lock during dispatch; empty and expired pointers are allowed.
method – The non-null member-function pointer.
- Throws:
Any – exception from allocating the shared handler.
See: Bound Callbacks
- Returns:
A copyable callable retaining the current target and checking recipient lifetime at dispatch.
-
EventsPtr erbsland::event::currentEvents()
Access the events interface for the event loop currently running on this thread.
The calling thread must be running an event loop.
- Returns:
The events interface for the loop bound to the current thread.
-
class Event
A single event.
Public Functions
-
inline explicit Event(const EventId identifier) noexcept
Create an event of a given type.
- Parameters:
identifier – The event identifier.
-
inline Event(const EventId identifier, EventDataUniquePtr data) noexcept
Create an event of a given type with optional data.
- Parameters:
identifier – The event identifier.
data – Optional event data.
-
inline const EventDataUniquePtr &data() const noexcept
Optional event data.
-
inline explicit Event(const EventId identifier) noexcept
-
class EventBackend
A backend for event loops.
Backends provide external event sources such as timers, files or network IO.
Subclassed by erbsland::event::impl::SchedulerBackend, erbsland::network::impl::NetworkBackend, erbsland::system::impl::SystemBackend, erbsland::util::impl::UtilitiesBackend
Public Functions
-
virtual EventBackendId backendId() const noexcept = 0
Get the unique backend identifier.
-
virtual void attach(EventBackendTargetWeakPtr target, EventLoopDriverWeakPtr driver) = 0
Attach this backend to a backend target.
- Parameters:
target – The target for events generated by this backend.
driver – The native wait and wake driver for attached event sources.
-
virtual void poll(time::TimePoint now) = 0
Poll the backend for due events.
- Parameters:
now – The current time point used by the loop for this poll cycle.
-
virtual EventBackendId backendId() const noexcept = 0
-
class EventBackendId
Represents an event backend type.
Public Types
-
using Value = uint32_t
The underlying value type.
-
using Value = uint32_t
-
class EventBackendIdInfo
Information about a backend id for diagnostics.
-
class EventBackendTarget
A target interface for event backends.
Subclassed by erbsland::event::impl::EventLoop
-
using erbsland::event::EventCallback = std::function<void()>
A callback that is executed by an event loop.
-
class EventData
The base class for event data.
If an event has additional data, it is stored as a subclass of this class.
Subclassed by erbsland::event::impl::CallbackEventData, erbsland::event::impl::TimerEventData
-
class EventEditor
Common interface for editing handlers owned by an event source.
Sources own their editors and return them by reference. The source and target accessors exist primarily for generic code that works with heterogeneous editors; regular code uses the typed
on...()methods.Subclassed by erbsland::event::impl::CommonEventEditor
Public Functions
-
virtual ~EventEditor()
Destroy the event editor.
-
virtual EventSourcePtr source() const = 0
Retain and access the source that owns this editor.
Source ownership must remain valid for the editor’s lifetime.
- Returns:
The owning event source.
-
virtual EventsPtr target() const noexcept = 0
Retain and access the target on which callbacks are executed.
- Returns:
The callback target.
-
virtual ~EventEditor()
-
class EventId
Represents a type of event.
Public Types
-
using Value = uint32_t
The underlying value type.
-
using Value = uint32_t
-
class EventIdInfo
Information about an event id for diagnostics.
-
class EventLoop : public erbsland::event::Events
An event loop.
Each event loop owns its queue and backend registry.
See: Queue Capacity and Error Policies
Subclassed by erbsland::event::impl::EventLoop
Public Functions
-
virtual void run() = 0
Run this event loop until stopped.
- Throws:
system::PlatformError – If the native driver wait fails.
-
virtual bool runOnce() = 0
Run one event-loop cycle without a maximum wait time.
- Throws:
system::PlatformError – If the native driver wait fails.
- Returns:
trueif an event was processed.
-
virtual bool runOnce(time::TimeDelta maximumWait) = 0
Run one event-loop cycle with a maximum wait time.
- Parameters:
maximumWait – The maximum time to wait for an event.
- Throws:
system::PlatformError – If the native driver wait fails.
- Returns:
trueif an event was processed.
-
virtual std::size_t runUntilIdle() = 0
Run event-loop cycles until there is no immediate work left.
- Throws:
system::PlatformError – If the native driver wait fails.
- Returns:
The number of processed events.
-
virtual void stop() noexcept = 0
Stop this event loop.
-
virtual void quit() noexcept = 0
Close admission and drain accepted events using reserved quit control.
-
virtual bool isRunning() const noexcept = 0
Test if this event loop is running.
-
virtual bool isQuitRequested() const noexcept = 0
Test if this event loop was requested to quit.
-
virtual std::size_t queuedEventCount() const noexcept = 0
Get a snapshot of ordinary waiting events, excluding scheduler and shutdown control work.
-
virtual bool hasError() const noexcept = 0
Test if a callback exception was captured.
-
virtual std::exception_ptr takeError() noexcept = 0
Take the oldest captured callback exception.
-
virtual void setErrorHandler(EventLoopErrorHandler handler) = 0
Set the error handler for callback and backend
err::RuntimeErrorexceptions.- Parameters:
handler – The handler to call after capturing an exception.
-
virtual void registerBackend(EventBackendPtr backend) = 0
Register a backend.
- Parameters:
backend – The backend to register.
Public Static Functions
-
static EventLoopPtr create(const EventLoopOptions &options = {})
Create an event loop with the default backend.
- Parameters:
options – Capacity and default error policies, copied into the loop. Must be valid and must not require managed-application delivery.
- Throws:
system::PlatformError – If a default native driver cannot be created.
- Returns:
The new event loop.
-
static EventLoopPtr create(EventBackendPtr backend, const EventLoopOptions &options = {})
Create an event loop with one initial backend.
- Parameters:
backend – The backend to register.
options – Capacity and default error policies, copied into the loop. Must be valid and must not require managed-application delivery.
- Throws:
system::PlatformError – If a default native driver cannot be created.
- Returns:
The new event loop.
-
static EventLoopPtr create(EventLoopDriverPtr driver, const EventLoopOptions &options = {})
Create an event loop with a custom native driver.
- Parameters:
driver – The non-null driver to use.
options – Capacity and default error policies, copied into the loop. Must be valid and must not require managed-application delivery.
- Returns:
The new event loop.
-
virtual void run() = 0
-
class EventLoopDriver
The native wait and wake driver for an event loop.
A driver is called only by its owning event loop, except for
wake(), which is thread-safe. Native event sources use platform-specific implementation interfaces derived from this class.Subclassed by erbsland::event::impl::EpollEventLoopDriver, erbsland::event::impl::KqueueEventLoopDriver, erbsland::event::impl::WindowsEventLoopDriver
Public Functions
-
virtual void wait() = 0
Wait until the driver is woken or a native source is ready.
- Throws:
system::PlatformError – If the native wait fails.
-
virtual void wait(time::TimeDelta maximumWait) = 0
Wait until the driver is woken, a native source is ready, or the maximum wait elapsed.
A zero or negative duration only polls immediately available native events.
- Parameters:
maximumWait – The maximum wait duration.
- Throws:
system::PlatformError – If the native wait fails.
-
virtual void wake() noexcept = 0
Wake the driver.
This method is thread-safe.
Public Static Functions
-
static EventLoopDriverPtr createDefault()
Create the default driver for the current platform.
- Throws:
system::PlatformError – If the native queue or wake mechanism cannot be created.
- Returns:
A kqueue, epoll, or IOCP based driver.
-
virtual void wait() = 0
-
enum class erbsland::event::EventLoopErrorAction : uint8_t
The action to take after an event-loop error.
Values:
-
enumerator Continue
Continue the event loop.
-
enumerator Stop
Stop this event loop.
-
enumerator Continue
-
using erbsland::event::EventLoopErrorHandler = std::function<EventLoopErrorAction(std::exception_ptr error)>
A callback that decides how an event loop reacts to an
err::RuntimeErrorexception.
-
enum class erbsland::event::EventLoopErrorPolicy : uint8_t
The default policy for event callback
err::RuntimeErrorfailures.Other exceptions bypass the policy and propagate to the loop caller.
Values:
-
enumerator Ignore
Discard the exception and continue.
-
enumerator Store
Store the exception and continue.
-
enumerator Quit
Store the exception and gracefully quit the loop.
-
enumerator FailApplication
Store and forward the exception to the owning application.
-
enumerator Ignore
-
class EventLoopOptions
Immutable-at-installation capacity and default failure policies for an event loop.
See: Queue Capacity and Error Policies
Public Functions
-
inline std::size_t maximumQueuedEvents() const noexcept
Get the ordinary waiting-event limit; zero means unlimited.
-
inline EventLoopOptions &setMaximumQueuedEvents(std::size_t value) noexcept
Set the ordinary waiting-event limit; zero means unlimited.
-
inline EventQueueOverflowAction queueOverflowAction() const noexcept
Get the queue-overflow action.
-
inline EventLoopOptions &setQueueOverflowAction(EventQueueOverflowAction value) noexcept
Set the queue-overflow action.
-
inline EventLoopErrorPolicy errorPolicy() const noexcept
Get the default
err::RuntimeErrorcallback policy.
-
inline EventLoopOptions &setErrorPolicy(EventLoopErrorPolicy value) noexcept
Set the default
err::RuntimeErrorcallback policy.
-
inline std::size_t maximumQueuedEvents() const noexcept
-
class EventQueueFullError : public erbsland::err::RuntimeError
An event could not be admitted to a full queue.
-
enum class erbsland::event::EventQueueOverflowAction : uint8_t
The action when an event queue reaches capacity.
Values:
-
enumerator Terminate
Terminate the process.
-
enumerator FailApplication
Forward a queue-full failure to the owning application.
-
enumerator Quit
Reject new work and drain accepted events.
-
enumerator Block
Wait for space; terminate if the consumer would wait.
-
enumerator Ignore
Discard the incoming event.
-
enumerator Terminate
-
class EventRegistry
The registry to manage event and backend ids.
Public Functions
-
explicit EventRegistry(PrivateTag)
Create the event registry.
-
EventId registerEvent(text::String name, text::String description = {})
Register a custom event type.
- Parameters:
name – Must be a reverse domain name. E.g.
com.example.myapp.MyEvent. Valid characters are-_.a-zA-Z0-9. The maximum length is 200 code-points.description – A description of the event type. The maximum length is 2000 code-points.
-
bool isRegistered(EventId identifier) const noexcept
Test if an event is registered.
- Parameters:
identifier – The event identifier.
-
bool isRegistered(const text::String &name) const noexcept
Test if an event is registered.
- Parameters:
name – The event name.
-
EventId getEventId(const text::String &name) const noexcept
Get the event identifier from a given ID.
- Parameters:
name – The event name.
- Returns:
The event identifier or
noEvent()if the event is not registered.
-
EventIdInfo getEventInfo(EventId identifier) const noexcept
Access event information for a given ID.
- Parameters:
identifier – The event identifier.
- Returns:
The event information or empty event information if the event is not registered.
-
EventBackendId registerBackend(text::String name, text::String description = {})
Register a custom backend type.
- Parameters:
name – Must be a reverse domain name. E.g.
com.example.myapp.MyBackend. Valid characters are-_.a-zA-Z0-9. The maximum length is 200 code-points.description – A description of the backend type. The maximum length is 2000 code-points.
-
bool isRegistered(EventBackendId identifier) const noexcept
Test if a backend is registered.
- Parameters:
identifier – The backend identifier.
-
bool isBackendRegistered(const text::String &name) const noexcept
Test if a backend is registered.
- Parameters:
name – The backend name.
-
EventBackendId getBackendId(const text::String &name) const noexcept
Get the backend identifier from a given ID.
- Parameters:
name – The backend name.
- Returns:
The backend identifier or
noBackend()if the backend is not registered.
-
EventBackendIdInfo getBackendInfo(EventBackendId identifier) const noexcept
Access backend information for a given ID.
- Parameters:
identifier – The backend identifier.
- Returns:
The backend information or empty backend information if the backend is not registered.
Public Static Functions
-
static inline constexpr EventId noEvent() noexcept
Get the no-event identifier.
This is an alias for
EventId{}for making code more readable.
-
static inline constexpr EventBackendId noBackend() noexcept
Get the no-backend identifier.
This is an alias for
EventBackendId{}for making code more readable.
-
static inline constexpr EventBackendId schedulerBackend() noexcept
Get the scheduler backend identifier.
-
static inline constexpr EventBackendId systemBackend() noexcept
Get the system backend identifier.
-
static inline constexpr EventBackendId utilitiesBackend() noexcept
Get the utilities backend identifier.
-
static inline constexpr EventBackendId networkBackend() noexcept
Get the network backend identifier.
-
explicit EventRegistry(PrivateTag)
-
class Events
A target for thread-safe event posting and callback invocation.
Subclassed by erbsland::event::EventLoop
Public Functions
-
virtual void post(Event event) = 0
Post an event to this target.
- Parameters:
event – The event to post.
-
virtual void invoke(EventCallback callback) = 0
Invoke a callback on this target.
- Parameters:
callback – The callback to execute on the target event loop.
-
virtual void invokeAfter(time::TimeDelta delay, EventCallback callback) = 0
Invoke a callback on this target after a delay.
A zero or negative delay queues the callback like
invoke().- Parameters:
delay – The delay before queuing the callback.
callback – The callback to execute on the target event loop.
-
template<typename T>
inline T &get() Access a backend frontend interface.
The requested backend must be available and expose the interface
T.- Template Parameters:
T – The public backend frontend interface.
- Returns:
The requested backend frontend.
-
inline EventTimerPtr createTimer(EventCallback callback)
Create an inactive timer for this target.
- Parameters:
callback – The callback to execute when the timer fires.
-
virtual void post(Event event) = 0
-
class EventScheduler
The public scheduler frontend for an events interface.
Subclassed by erbsland::event::impl::SchedulerBackend
Public Functions
-
virtual void invokeAfter(time::TimeDelta delay, EventCallback callback) = 0
Invoke a callback after a delay.
A zero or negative delay queues the callback immediately.
- Parameters:
delay – The delay before queuing the callback.
callback – The callback to execute on the target event loop.
-
virtual EventTimerPtr createTimer(EventCallback callback) = 0
Create an inactive timer.
- Parameters:
callback – The callback to execute when the timer fires.
Public Static Functions
-
static inline constexpr EventBackendId backendId() noexcept
The backend identifier for scheduler implementations.
-
virtual void invokeAfter(time::TimeDelta delay, EventCallback callback) = 0
-
class EventSource : public std::enable_shared_from_this<EventSource>
Base class for shared event sources owned by one event loop.
Each concrete source owns one stable event editor and exposes it through
events(). Returning a reference makes the editor’s non-owning role explicit, whileEventEditor::source()lets generic code retain the source if needed.Subclassed by erbsland::network::Connection, erbsland::network::HostLookup, erbsland::network::HttpClientRequest, erbsland::network::HttpClientResponse, erbsland::network::HttpClientSession, erbsland::network::HttpServer, erbsland::network::HttpServerRequest, erbsland::network::HttpServerSession, erbsland::network::TcpListener, erbsland::network::UdpSocket, erbsland::system::Subprocess, erbsland::util::WorkerPool
Public Functions
-
const EventsPtr &ownerEvents() const noexcept
Access the event loop that owns this source.
-
virtual EventEditor &events() = 0
Access the stable editor owned by this source.
Must be called on the owner event loop.
- Returns:
The source-owned editor.
-
const EventsPtr &ownerEvents() const noexcept
-
class EventSubscription
A move-only lifetime handle for one registered event callback.
Destroying or cancelling this handle prevents future callback invocations. A callback that already started may finish. Destroying the publisher automatically invalidates the subscription.
Public Functions
-
EventSubscription() = default
Create an inactive subscription.
-
inline ~EventSubscription()
Cancel this subscription.
-
inline void cancel() noexcept
Cancel this subscription.
-
inline bool isActive() const noexcept
Test whether this subscription is still active.
-
inline explicit EventSubscription(impl::EventSubscriptionControlPtr control) noexcept
Create a subscription from its internal control.
- Parameters:
control – The control owned by this subscription.
-
EventSubscription() = default
-
class EventThread
A one-shot thread that owns and runs one event loop.
start()can succeed only once.quit()requests graceful termination, whilejoin()only waits and never requests termination itself. Concrete implementations stop and join a started worker before destruction. The final owning pointer must not be released from the event thread itself.Subclassed by erbsland::event::ManagedEventThread, erbsland::event::UnmanagedEventThread
Public Functions
-
virtual void start() = 0
Start the event loop on a new worker thread.
The call returns after creating the worker; the event loop may not yet report itself as running. After a successful call,
isStarted()remainstruefor the lifetime of this object. Must not be called more than once, including after the thread has been joined.- Throws:
std::system_error – If the native worker thread cannot be created.
-
virtual void quit() noexcept = 0
Request graceful termination of the event loop.
This operation is idempotent, returns without waiting, and can be called before
start(). Events queued before the quit request are processed before the loop terminates.
-
virtual void join() = 0
Wait until the thread has finished.
This operation does not request termination. It blocks while the worker is running, returns immediately if the thread was never started or was already joined, and leaves
isStarted()unchanged. Exceptions escaping the worker are not transported through this call and terminate the process instead. Must not be called from this event thread.- Throws:
std::system_error – If the native join operation fails.
-
virtual bool isStarted() const noexcept = 0
Test whether
start()completed successfully at least once.- Returns:
trueafter the one successful start, including after the worker terminated and was joined.
-
virtual bool isRunning() const noexcept = 0
Test whether the event loop is currently running on the worker.
- Returns:
trueonly while the event loop is executing; this is not a start or completion barrier.
-
virtual EventLoop &eventLoop() noexcept = 0
Access the event loop owned by this thread.
- Returns:
A reference that remains valid for the lifetime of this thread object.
-
virtual EventsPtr events() noexcept = 0
Access the event-target interface of the owned loop.
- Returns:
A shared event target suitable for posting work to this thread.
-
virtual void start() = 0
-
class EventTimer
A thread-safe timer for scheduled event callbacks.
Subclassed by erbsland::event::impl::EventTimer
Public Functions
-
virtual void startOnce(time::TimeDelta delay) = 0
Start this timer once after
delay.A zero or negative delay schedules the timer for immediate execution.
- Parameters:
delay – The delay before executing the callback.
-
virtual void startFixedDelay(time::TimeDelta interval) = 0
Start this timer repeatedly with a fixed delay after each callback finishes.
- Parameters:
interval – The positive interval between callback completion and the next execution.
-
virtual void startFixedRate(time::TimeDelta interval) = 0
Start this timer repeatedly with a fixed rate.
Missed ticks are skipped and never queued as catch-up bursts.
- Parameters:
interval – The positive interval between scheduled callback times.
-
virtual void stop() noexcept = 0
Stop this timer.
-
virtual bool isActive() const noexcept = 0
Test if this timer is active or has a callback queued for execution.
-
virtual EventTimerMode mode() const noexcept = 0
Get the current timer mode.
-
virtual void startOnce(time::TimeDelta delay) = 0
-
enum class erbsland::event::EventTimerMode : uint8_t
The current scheduling mode of an event timer.
Values:
-
enumerator Inactive
The timer is inactive.
-
enumerator Once
The timer runs once.
-
enumerator FixedDelay
The timer repeats with a delay after each callback.
-
enumerator FixedRate
The timer repeats on a fixed cadence.
-
enumerator Inactive
-
class ManagedEventThread : public erbsland::event::EventThread
An application-managed thread that runs an event loop.
Managed event threads are created by
core::Application::createEventThread()and are quit together with the application event loop.Subclassed by erbsland::event::impl::ManagedEventThread
-
class UnmanagedEventThread : public erbsland::event::EventThread
A standalone thread that runs an event loop.
Unmanaged event threads are not registered with
core::Applicationand are not quit by application shutdown.Subclassed by erbsland::event::impl::UnmanagedEventThread
Public Static Functions
-
static UnmanagedEventThreadPtr create(const EventLoopOptions &options = {})
Create an unmanaged event thread.
- Parameters:
options – Capacity and default error policies, copied into the loop. Must be valid and must not require managed-application delivery.
- Returns:
The new, unstarted event thread.
-
static UnmanagedEventThreadPtr create(const EventLoopOptions &options = {})