Supervision module#
The supervision module provides lifecycle event publication, state querying, and observer registration for actors/components running on local or remote localities.
Overview#
Several core operations are exposed, each with a local (synchronous) call and
a remote (locality-qualified, future-returning or launch::sync_policy)
call:
Functions#
Function |
Description |
|---|---|
Register an observer for activity-state transitions of all targets. |
|
Publishing events#
-
hpx::future<hpx::supervision::publish_result> hpx::supervision::publish_event(hpx::id_type const &locality, hpx::id_type const &target, hpx::supervision::event ev, std::uint64_t epoch = 0)
-
hpx::supervision::publish_result hpx::supervision::publish_event(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &target, hpx::supervision::event ev, std::uint64_t epoch = 0, hpx::error_code &ec = hpx::throws)
-
hpx::supervision::publish_result hpx::supervision::publish_event(hpx::id_type const &target, hpx::supervision::event ev, std::uint64_t epoch = 0, hpx::error_code &ec = hpx::throws)
Publish a lifecycle event for
target. Events are visible immediately to local observers; remote observers are notified within roughly one to two parcel round-trips. Publishing non-terminal events is not idempotent - each call creates a distinct, timestamped record.event::completedandevent::failedare latched: the first terminal publication for a target returnspublish_result::applied; every later terminal publication for that target is a no-op that returnspublish_result::already_terminal.
Querying lifecycle state#
-
hpx::future<hpx::supervision::lifecycle_state> hpx::supervision::query_state(hpx::id_type const &locality, hpx::id_type const &target)
-
hpx::supervision::lifecycle_state hpx::supervision::query_state(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &target, hpx::error_code &ec = hpx::throws)
-
hpx::supervision::lifecycle_state hpx::supervision::query_state(hpx::id_type const &target, hpx::error_code &ec = hpx::throws)
Query the most recently observed lifecycle state for
target. Includes a sequence number for gap detection and a staleness error code for remote queries whose result may lag the latest event.
Registering observers#
-
hpx::future<hpx::id_type> hpx::supervision::register_observer(hpx::id_type const &locality, hpx::id_type const &target, hpx::supervision::lifecycle_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt)#
-
hpx::id_type hpx::supervision::register_observer(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &target, hpx::supervision::lifecycle_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt, hpx::error_code &ec = hpx::throws)#
-
hpx::id_type hpx::supervision::register_observer(hpx::id_type const &target, hpx::supervision::lifecycle_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt, hpx::error_code &ec = hpx::throws)#
Register
callbackto be invoked on lifecycle events oftarget, returning an observer handle usable withunregister_observer. Local callbacks fire synchronously within the publish call; remote callbacks fire via a retried parcel. Ifepoch_filteris set, the observer only receives notifications (including the initial state snapshot delivered at registration time) whose epoch matches; by default the observer receives notifications for every epoch.
Unregistering observers#
-
hpx::future<void> hpx::supervision::unregister_observer(hpx::id_type const &locality, hpx::id_type const &observer_handle)
-
void hpx::supervision::unregister_observer(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &observer_handle, hpx::error_code &ec = hpx::throws)
-
void hpx::supervision::unregister_observer(hpx::id_type const &observer_handle, hpx::error_code &ec = hpx::throws)
Unregister a previously registered observer.
observer_handlemust have been obtained fromregister_observer; a handle obtained fromregister_activity_observer, or any handle never returned by either registration function, is rejected.
Removing target state#
-
hpx::future<void> hpx::supervision::remove_target(hpx::id_type const &locality, hpx::id_type const &target)
-
void hpx::supervision::remove_target(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &target, hpx::error_code &ec = hpx::throws)
-
void hpx::supervision::remove_target(hpx::id_type const &target, hpx::error_code &ec = hpx::throws)
Clear all locally tracked state for
target. Unlikeunregister_observer, which removes a single previously registered observer handle,remove_targetunconditionally forgets every piece of local state held fortarget- its recorded lifecycle state and current epoch, and any observers still registered for it - regardless of any specific observer handle. Intended for callers that knowtargetwill never be queried or observed again locally (e.g. after a failed registration that seeded some state for it, or once a peer has been evicted), so that local state does not accumulate indefinitely.
Waiting for terminal events#
-
hpx::future<hpx::supervision::lifecycle_state> hpx::supervision::await_terminal(hpx::id_type const &locality, hpx::id_type const &target, std::uint64_t epoch = 0, std::chrono::steady_clock::duration timeout = std::chrono::steady_clock::duration::max())#
-
hpx::supervision::lifecycle_state hpx::supervision::await_terminal(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &target, std::uint64_t epoch = 0, std::chrono::steady_clock::duration timeout = std::chrono::steady_clock::duration::max(), hpx::error_code &ec = hpx::throws)#
-
hpx::future<hpx::supervision::lifecycle_state> hpx::supervision::await_terminal(hpx::id_type const &target, std::uint64_t epoch = 0, std::chrono::steady_clock::duration timeout = std::chrono::steady_clock::duration::max())#
Asynchronously wait, one-shot and without blocking a worker thread, and the
launch::sync_policyoverload waits synchronously untiltargetreaches a terminal event (event::completedorevent::failed) withinepoch. If a terminal event has already been recorded fortargetinepoch, the returned future is immediately satisfied with that state. Waits are scoped to a single epoch: iftarget’s epoch advances pastepochbefore a terminal event occurs, any outstanding waiter for the stale epoch is invalidated. A waiter that reaches neither of these outcomes is bounded bytimeout(or a built-in default iftimeoutis left at its sentinel valuestd::chrono::steady_clock::duration::max()), after which it is swept and invalidated. Dispatch is routed locally whentarget’s supervision manager lives on the calling locality, and remotely (via a registered distributed action) otherwise.
Checking dispatch admission#
-
hpx::supervision::dispatch_outcome hpx::supervision::check_admission(hpx::id_type const &target, std::uint64_t epoch = 0)
Check whether
targetcurrently admits new dispatch underepoch, i.e. whether it is safe to schedule or route work to it right now. This is a pure,noexceptlocal read of the same terminal latch state consulted byawait_terminal: it returnsdispatch_outcome::rejected_fencediftargethas already latched a terminal event (event::completedorevent::failed) underepoch, anddispatch_outcome::admittedotherwise. Unlikepublish_result, which reports how a publication was resolved,dispatch_outcomeanswers the separate, consumer-side question of whether dispatch should proceed; it must only be called on the localitytargetlives on.This admission fence is scoped to a single locality’s latch state: it reflects only terminal events published to the supervision manager hosting
target, and it fails open (returnsadmitted) whentargetis unknown locally, including when its terminal event was only ever published elsewhere. There is no built-in mechanism that propagates terminal latch state across localities - observer registration delivers notifications, not admission state. Any additional locality that needs to fence its own dispatch decisions ontargetmust independently mirror or route to the owning locality’s state; this module does not provide that for you.
Registering activity observers#
-
hpx::future<hpx::id_type> hpx::supervision::register_activity_observer(hpx::id_type const &locality, hpx::supervision::activity_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt)#
-
hpx::id_type hpx::supervision::register_activity_observer(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::supervision::activity_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt, hpx::error_code &ec = hpx::throws)#
-
hpx::id_type hpx::supervision::register_activity_observer(hpx::supervision::activity_callback const &callback, std::optional<std::uint64_t> epoch_filter = std::nullopt, hpx::error_code &ec = hpx::throws)#
Register
callbackto observe activity-state transitions (betweenhpx::supervision::activity_state::inactiveandactive) of all targets tracked by a locality’s supervision manager. Unlikeregister_observer, none of these overloads take atargetparameter: the feature reports on every target the addressed manager tracks rather than on a single one.Registering an activity observer for an already-active target triggers a replay of its current state. The snapshot of tracked state and the insertion of the observer are performed atomically under the manager’s internal lock, which guarantees exactly-once delivery: the observer receives either the replay or a live transition that raced with registration, but never both and never neither.
Note that the notification itself (replay or live) is delivered after the lock is released. Its delivery order relative to any other concurrent live notification for the same target is not guaranteed, only the exactly-once property is guaranteed, not relative ordering.
Activity notifications are a pure discovery/notification signal: unlike
publish_event, registering or unregistering an activity observer never feeds the terminal latch consulted bycheck_admission.If
epoch_filteris set,callbackonly receives notifications - including the registration-time replay - whose epoch matches; by default it receives notifications regardless of epoch.
Unregistering activity observers#
-
hpx::future<void> hpx::supervision::unregister_activity_observer(hpx::id_type const &locality, hpx::id_type const &observer_handle)
-
void hpx::supervision::unregister_activity_observer(hpx::launch::sync_policy, hpx::id_type const &locality, hpx::id_type const &observer_handle, hpx::error_code &ec = hpx::throws)
-
void hpx::supervision::unregister_activity_observer(hpx::id_type const &observer_handle, hpx::error_code &ec = hpx::throws)
Unregister a previously registered activity observer.
observer_handlemust have been obtained fromregister_activity_observer; a handle obtained fromregister_observer, or any handle never returned by either registration function, is rejected.
See the API reference of this module for more details.