Jump to content

Operator Lifecycle

From RidgeRun Developer Wiki

🚧 Documentation is under development

The Holoscan SDK guide is currently under active development. Some sections may be incomplete or change without notice.

Questions? Contact RidgeRun or email to support@ridgerun.com.

Contents Pin





Operator Lifecycle

An operator receives data, performs one step of application work, and publishes a result. Its class describes the interface during graph construction and performs the work after the graph starts.

Keep the two moments separate:

  • Authoring declares ports, parameters, and execution rules.
  • Running selects input data, calls the operator, and manages its resources.

See where each method runs

Phase What happens Common code
Authoring The application creates the operator and connects it to other operators. Constructor and setup()
Compilation Holoscan checks the declarations and creates an ExecutionPlan. contract() and graph connections
Startup The run prepares the resources needed by the active graph. start() or a lifecycle callback
Processing The runtime selects the inputs for one activation and calls compute(). Read inputs, do the work, and publish outputs
Shutdown The run stops new activations and releases resources. stop() and cleanup callbacks

A constructor, setup(), or contract() describes the operator. Avoid opening devices, starting worker threads, or allocating resources that belong to one run in those methods. Put that work in start(), compute(), or stop() according to its lifetime.

Build a small operator

The following operator reads one integer, doubles it, and publishes the result. It shows the usual order: declare an Input<T> and an Output<T>, select one input per activation, read it with receive_data(), and publish with emit().

#include <cstdint>
#include <utility>

#include <holoscan/core/execution_context.hpp>
#include <holoscan/core/operator.hpp>
#include <holoscan/core/operator_spec.hpp>
#include <holoscan/core/port.hpp>
#include <holoscan/core/temporal_contract.hpp>

class DoubleOp final : public holoscan::Operator<> {
 public:
  holoscan::Input<std::int32_t> input;
  holoscan::Output<std::int32_t> output;

  void setup(holoscan::OperatorSpec& spec) override {
    spec.input(input, "input");
    spec.output(output, "output");
  }

  holoscan::Contract contract() const override {
    holoscan::Contract result;
    result.trigger(holoscan::OnEach{input});
    return result;
  }

  holoscan::expected<void, holoscan::Error> compute(
      holoscan::ExecutionContext&) override {
    auto value = input.receive_data();
    if (!value) {
      return holoscan::make_unexpected(std::move(value).error());
    }
    return output.emit(*value * 2);
  }
};

Input<T> and Output<T> declare the value types at the operator boundary. OnEach tells the runtime to activate the operator when a new value is available on input. The next page explains how values, samples, and payload types move through those ports.

Choose the lifecycle style

Use start() and stop() for simple initialization and cleanup. Use staged lifecycle callbacks when startup needs separate phases such as discovery, allocation, warm-up, or device binding. Register them through spec.lifecycle().

Keep lifecycle code focused on the resources owned by the operator. A restart can run startup and cleanup again, so release the resources associated with the active run before creating them again.


Learn more about lifecycle callbacks
The Lifecycle Callbacks and Restart Control guide covers staged callback phases, ordering, callback results, and restart behavior.


Continue the flow


Related Examples



Cookies help us deliver our services. By using our services, you agree to our use of cookies.