Supervision dispatch module#
The supervision dispatch module provides peer discovery, cooperative
lifecycle management, failure detection, and fenced action dispatch across
localities, built on top of the supervision
module’s lifecycle events and admission checks. See that module’s reference
for the semantics of hpx::supervision::check_admission and
hpx::supervision::dispatch_outcome; this page documents only the
dispatch-specific surface layered on top of them. For the narrative on
initialization ordering, one-shot discovery, shadow-state semantics, and
client-side filtering versus fenced-dispatch admission, see
Supervision dispatch.
Overview#
Functions#
Function |
Description |
|---|---|
Types#
Type |
Description |
|---|---|
Lifecycle initialization and shutdown#
-
hpx::shared_future<hpx::supervision::registry> hpx::supervision::init(hpx::chrono::steady_duration const &discovery_timeout = hpx::supervision::default_discovery_timeout)
-
hpx::supervision::registry hpx::supervision::init(hpx::launch::sync_policy, hpx::chrono::steady_duration const &discovery_timeout = hpx::supervision::default_discovery_timeout)
Performs one-shot, idempotent initialization of the supervision-dispatch runtime for this locality: creates a local registry, publishes
event::startedbefore its symbol name is registered, registers that name, and performs a singlediscover_and_join()pass. Callinginit()while already active is a no-op; concurrent callers duringinitializingattach to the in-flight operation instead of racing it.
-
void hpx::supervision::finalize()
Performs one-shot, idempotent teardown of the runtime previously started by
init(): publishesevent::completedat the current/unchanged epoch, unregisters the registry’s symbol name, and releases the registry. A no-op unless the runtime is currentlyactive.
-
bool hpx::supervision::is_initialized() noexcept
Returns whether the runtime is currently
active. Never blocks; safe to call from any thread, including whileinit()/finalize()is in flight.
Peer discovery#
-
struct hpx::supervision::discovered_peer#
A peer whose registry symbol name resolved during a
discover_peers()call. Holdslocality,registry_client, andjoin_epoch.discover_peers()leavesjoin_epochathpx::supervision::unjoined_epoch(never0, which is a legitimate join epoch);fan_out_join()fills it in with the epoch recorded byregistry::join().localityis cached for convenience but is never independently resolved or validated: it is always derived fromregistry_clientitself (seeregistry::get_locality()), since exactly one registry exists per locality.
-
std::vector<hpx::supervision::discovered_peer> hpx::supervision::discover_peers(hpx::chrono::steady_duration const &timeout = hpx::supervision::default_discovery_timeout)#
Performs a one-time discovery pull: concurrently resolves the pinned registry name of every remote locality, bounded by a single wait for
timeout. Localities that have not yet calledinit()are silently excluded rather than causing a hang or failure.
-
std::vector<hpx::supervision::discovered_peer> hpx::supervision::fan_out_join(...)#
Fans out
join()calls fromlocal_registryto every entry inpeers. Reusesregistry::join()’s reservation/idempotency machinery, so repeated or overlapping calls never create more than one shadow per peer locality.Returns a
discovered_peerfor each peer whosejoin()call settled successfully withintimeout, in the same relative order aspeers. Peers whosejoin()call did not settle in time are omitted from the result (rather than left as gaps or defaulted entries), so the returned vector is a same-order subset ofpeers, not index-aligned with it.
-
std::vector<hpx::supervision::discovered_peer> hpx::supervision::discover_and_join(hpx::supervision::registry const &local_registry, hpx::chrono::steady_duration const &timeout = hpx::supervision::default_discovery_timeout)#
Composes a single reactive discovery-and-join pass: one
discover_peers()pull followed by onefan_out_join()call. Introduces no polling, timer, or repeated broadcast of its own.Returns the same
discovered_peervector produced byfan_out_join()for the peers it discovered.
State query and event publication#
-
hpx::future<hpx::supervision::lifecycle_state> hpx::supervision::query_state(hpx::supervision::registry const &handle)#
-
hpx::supervision::lifecycle_state hpx::supervision::query_state(hpx::launch::sync_policy, hpx::supervision::registry const &handle, hpx::error_code &ec = hpx::throws)#
-
hpx::future<hpx::supervision::lifecycle_state> hpx::supervision::query_state(hpx::supervision::registry const &handle, hpx::supervision::discovered_peer const &peer)#
-
hpx::supervision::lifecycle_state hpx::supervision::query_state(hpx::launch::sync_policy, hpx::supervision::registry const &handle, hpx::supervision::discovered_peer const &peer, hpx::error_code &ec = hpx::throws)#
The self variants resolve both locality and target to
hpx::find_here()and query it on the local locality; the peer variants resolve both locality and target frompeer.localityinstead -handleis accepted only for overload resolution and symmetry with the self variants, and is otherwise unused in that case. Each overload is a thin forwarder over the corresponding raw-idquery_state()overload in Supervision module; see that module’s reference for the fields of the returnedlifecycle_state, including theepochvalue useful for recovering the epoch a handle’s locality was started at.
-
hpx::future<hpx::supervision::publish_result> hpx::supervision::publish_event(hpx::supervision::registry const &handle, hpx::supervision::event ev, std::uint64_t epoch = 0)#
-
hpx::supervision::publish_result hpx::supervision::publish_event(hpx::launch::sync_policy, hpx::supervision::registry const &handle, hpx::supervision::event ev, std::uint64_t epoch = 0, hpx::error_code &ec = hpx::throws)#
Handle-based convenience overloads of
hpx::supervision::publish_eventthat resolve both locality and target tohpx::find_here()instead of requiring the caller to name them explicitly. Thin forwarders over the raw-idpublish_event()overloads in Supervision module. There is no peer variant: a locality publishes lifecycle events only for itself, never on behalf of a peer. The default epoch value of 0 is only correct for a locality’s very first publication after init(); once the target’s real epoch has advanced, 0 is stale. Callers publishing events after the initial one should first obtain the current epoch - e.g. via query_state(hpx::launch::sync, handle).epoch - and pass it explicitly.”
Registry client#
-
class hpx::supervision::registry
A lightweight, self-supervising client handle for pairing with peer localities; mirrors a peer’s lifecycle state locally via
join()and can itself be discovered by name in AGAS.-
hpx::future<hpx::supervision::joined_peer> join(hpx::id_type const &peer_locality) const#
-
hpx::supervision::joined_peer join(hpx::launch::sync_policy, hpx::id_type const &peer_locality, hpx::error_code &ec = hpx::throws) const#
Joins a peer locality: creates (or reuses) local supervision state mirroring the peer’s lifecycle. The returned
joined_peer::targetispeer_localityitself (not a generated local id) and is whatdispatch_work()colocates against.
-
hpx::future<std::vector<hpx::supervision::server::peer_snapshot>> snapshot_peers() const#
-
std::vector<hpx::supervision::server::peer_snapshot> snapshot_peers(hpx::launch::sync_policy, hpx::error_code &ec = hpx::throws) const#
Returns a point-in-time snapshot of all fully joined, non-evicting peers.
-
hpx::future<hpx::supervision::joined_peer> join(hpx::id_type const &peer_locality) const#
-
struct hpx::supervision::server::peer_snapshot
Plain-data view of a single joined peer:
peer_localityandjoin_epoch.
Fenced dispatch#
-
template<typename Action, typename ...Ts>
decltype(auto) hpx::supervision::dispatch_work(hpx::id_type const &target, std::uint64_t epoch, Ts&&... ts)# Dispatches
Actiontotargetunder supervision fencing. Performs a cheap, non-authoritative admission check on the caller’s locality to short-circuit an already-known-fenced target, then dispatches to the target’s own locality (viahpx::colocated) where an authoritative re-check against the same latch consulted byhpx::supervision::check_admissionruns immediately before the wrapped action executes, on the same thread, closing the admission/invocation race. See Supervision dispatch for the full client-side-filtering versus fenced-admission narrative and worked examples.- Throws
hpx::exceptionwithhpx::error::target_fencedif the target has latched a terminal event forepochsince the client-side check; the wrapped action is not invoked in that case.
Testing support#
The following are declared in hpx/supervision_dispatch/testing.hpp and are
not part of the stable public dispatch API; they exist solely to make
unit tests for this module deterministic:
-
std::vector<hpx::supervision::server::peer_snapshot> hpx::supervision::testing::local_snapshot_peers()
-
void hpx::supervision::testing::set_failure_detection_poll_timeout_for_testing(hpx::chrono::steady_duration const &timeout)
-
hpx::id_type hpx::supervision::testing::last_join_locality()
-
void hpx::supervision::testing::suspend_heartbeat_for_testing()
-
bool hpx::supervision::testing::failure_detection_sweep_in_flight_for_testing()
See the API reference of this module for more details, and Supervision module for the underlying lifecycle event, admission, and dispatch-outcome semantics this module builds on.