Motion Master 6.0.0-alpha.86
Next-generation motion control software
Loading...
Searching...
No Matches
mm::node::ProcedureManager Class Reference

Runs off-RT command-and-wait procedures and remembers how each one went. More...

#include <procedure_manager.h>

Public Member Functions

 ProcedureManager (DeviceManager &deviceManager)
 Binds the manager to the device set its procedures will run against.
 
 ~ProcedureManager ()
 Requests cancellation of every running procedure and waits for them to finish.
 
 ProcedureManager (const ProcedureManager &)=delete
 
ProcedureManageroperator= (const ProcedureManager &)=delete
 
std::expected< void, ProcedureErrorstart (uint16_t devicePosition, std::string name, std::vector< ProgressStep > steps, ProcedureBody body)
 Starts name on devicePosition, returning as soon as the run is under way.
 
std::optional< ProcedureSnapshotsnapshot (uint16_t devicePosition, std::string_view name) const
 The current or last-known state of name on devicePosition.
 
bool cancel (uint16_t devicePosition, std::string_view name)
 Asks the running name on devicePosition to stop.
 

Detailed Description

Runs off-RT command-and-wait procedures and remembers how each one went.

The MonitoringManager analogue for procedures: it owns the cancellable std::jthread each run executes on, the per-device exclusion that stops two runs colliding, and the snapshot a client polls. What it does not own is any knowledge of what a procedure does — bodies are supplied at start, so adding a procedure never touches this class.

Exclusion is per device, and it is the part a mutex cannot provide. The driver's control-plane lock serialises individual transactions (one SDO, one mailbox round-trip), but a procedure is a multi-second span of many transactions interleaved with sleeps. "This device is busy detecting its offset" is a span-level fact, so start rejects a second run on a device that already has one, and the claim is released when the thread exits — success, failure or cancellation alike.

Progress is polled, never pushed. This class holds no publish callback and names no WebSocket. Each snapshot is an accumulating full-array state in which finished steps keep their terminal status and value, which is what makes polling lossless: a step that starts and finishes between two polls is still visible as succeeded. See ProcedureSnapshot.

A snapshot outlives its run — retained per (device, procedure) until the next run of the same procedure replaces it — so a client that reconnects, or a user returning to a page, sees how the last run went rather than an empty state.

Retained snapshots are dropped when the device set is rebuilt. Positions may remap across a scan / reset, and a retained measurement rendered against a different physical drive is worse than no measurement at all. The rebuild is noticed by watching DeviceManager::topologyGeneration rather than by being told, which is what keeps DeviceManager unaware that procedures exist. A rescan can overlap any run, because a run holds no lock — so the sweep leaves a still-running entry alone and collects it later. See discardIfRescanned, where that is a correctness requirement rather than a nicety.

Thread-safe; start, snapshot and cancel may be called from any non-RT thread.

Constructor & Destructor Documentation

◆ ProcedureManager() [1/2]

mm::node::ProcedureManager::ProcedureManager ( DeviceManager deviceManager)
inlineexplicit

Binds the manager to the device set its procedures will run against.

Parameters
deviceManagerMust outlive this manager.

◆ ~ProcedureManager()

mm::node::ProcedureManager::~ProcedureManager ( )

Requests cancellation of every running procedure and waits for them to finish.

◆ ProcedureManager() [2/2]

mm::node::ProcedureManager::ProcedureManager ( const ProcedureManager )
delete

Member Function Documentation

◆ cancel()

bool mm::node::ProcedureManager::cancel ( uint16_t  devicePosition,
std::string_view  name 
)

Asks the running name on devicePosition to stop.

Cooperative: it requests the run's stop token and returns immediately. The body decides how promptly it notices — typically at its next step boundary or poll — after which the run finishes as kCancelled.

Returns
True if a run was in flight and got the stop request; false if there was nothing to cancel.

◆ operator=()

ProcedureManager & mm::node::ProcedureManager::operator= ( const ProcedureManager )
delete

◆ snapshot()

std::optional< ProcedureSnapshot > mm::node::ProcedureManager::snapshot ( uint16_t  devicePosition,
std::string_view  name 
) const

The current or last-known state of name on devicePosition.

Returns
The snapshot, or std::nullopt if that procedure never ran on that device since the last rebuild of the device set. (A caller that knows the procedure's step template can render an all-idle snapshot itself; the manager does not invent one, because it is only told a template when a run starts.)

◆ start()

std::expected< void, ProcedureError > mm::node::ProcedureManager::start ( uint16_t  devicePosition,
std::string  name,
std::vector< ProgressStep steps,
ProcedureBody  body 
)

Starts name on devicePosition, returning as soon as the run is under way.

The device is checked to exist before anything is spawned, so an unknown position fails here rather than surfacing later as a failed snapshot. On success the run is immediately visible via snapshot with status kRunning and a bumped runCount.

Parameters
devicePosition1-based bus position the procedure runs against.
nameProcedure identifier, e.g. "os-command"; scopes the retained snapshot.
stepsThe procedure's step template, in order, all idle.
bodyThe work to run (see ProcedureBody).
Returns
Void once started, or why it could not be (see ProcedureError).

The documentation for this class was generated from the following files: