holoscan::ops::OperatorRunner

Beta
View as Markdown

A class to run an operator independently from the workflow.

This class provides methods to push entities to the operator’s input ports and pop entities from the operator’s output ports. It also provides a method to run the operator separately from the workflow.

This class uses the GXFWrapper to set up and run the operator. The start() and stop() methods are called automatically when the operator is started or stopped. It uses AsynchronousCondition (with AsynchronousEventState::WAIT) to block the operator execution (calling the compute() method) from the holoscan executor, allowing the operator to run independently from the workflow via the run() method.

Input data can be pushed to the operator’s input ports using the push_input() method before calling run(). Output data can be retrieved from the operator’s output ports using the pop_output() method after calling run().

Both push_input() and pop_output() methods support the templated DataT type, which can be:

  • Primitive types (int, float, etc.)
  • Custom classes/structs (must be copyable/movable)
  • Smart pointers (std::shared_ptr, std::unique_ptr)
  • Standard library containers (std::vector, std::string, etc.)
  • std::any
  • holoscan::gxf::Entity
  • holoscan::TensorMap

Example types:

If the template type is not specified for pop_output() method, the method will return a holoscan::gxf::Entity.

Example usage:

#include <holoscan/ops/operator_runner.hpp>

This class is not thread-safe.

This is an experimental feature. The API may change in future releases.

Example

// Primitive types
runner.pop_output<int>("port");
runner.pop_output<float>("port");
// Custom types
runner.pop_output<MyCustomClass>("port");
// Smart pointers
runner.pop_output<std::shared_ptr<int>>("port");
runner.pop_output<std::shared_ptr<MyCustomClass>>("port");
// Standard containers
runner.pop_output<std::vector<float>>("port");
runner.pop_output<std::string>("port");
// std::any
runner.pop_output<std::any>("port");
// holoscan::gxf::Entity
runner.pop_output<holoscan::gxf::Entity>("port");
// holoscan::TensorMap
runner.pop_output<holoscan::TensorMap>("port");
// In the operator's initialize() method (after holoscan::Operator::initialize() is called):
// Create internal operators using the fragment
auto frag = fragment(); // fragment() is a method to get the fragment object in the operator
auto receiver_operator = frag->make_operator<FirstOp>("receiver",
holoscan::Arg("parameter_1", param_value_1),
holoscan::Arg("parameter_2", param_value_2));
// Wrap the operator with OperatorRunner
auto op_first_operator = std::make_shared<holoscan::ops::OperatorRunner>(receiver_operator);
// Create the next internal operator
auto next_operator = ...; // Create the next internal operator
// Wrap the next operator with OperatorRunner
auto op_next_operator_ = std::make_shared<holoscan::ops::OperatorRunner>(next_operator);
// In the operator's compute() method:
void compute(holoscan::InputContext& op_input, holoscan::OutputContext& op_output,
holoscan::ExecutionContext& context)
{
// Run the first internal operator
op_first_operator->run();
// Get output from the first internal operator
auto output = op_first_operator->pop_output("output");
if (!output) {
HOLOSCAN_LOG_ERROR("Failed to pop output from operator {} - {}",
op_first_operator->op()->name(),
output.error().what());
throw std::runtime_error(output.error().what());
}
// Push output to the next internal operator in the chain
auto result = op_next_operator_->push_input("input", output.value());
if (!result) {
HOLOSCAN_LOG_ERROR("Failed to push input to operator {} - {}",
op_next_operator_->op()->name(),
result.error().what());
throw std::runtime_error(result.error().what());
}
op_next_operator_->run();
// Get output from the next internal operator
auto next_output = op_next_operator_->pop_output("output");
if (!next_output) {
HOLOSCAN_LOG_ERROR("Failed to pop output from operator {} - {}",
op_next_operator_->op()->name(),
next_output.error().what());
throw std::runtime_error(next_output.error().what());
}
// Emit the output from this operator
op_output.emit(next_output.value(), "output");
}

Constructors

OperatorRunner

holoscan::ops::OperatorRunner::OperatorRunner(holoscan::ops::OperatorRunner::OperatorRunner(
const std::shared_ptr<holoscan::Operator> &op
)

Construct a new Operator Runner object.

Parameters

op
const std::shared_ptr<holoscan::Operator> &

The operator to run.


Methods

op

const std::shared_ptr<holoscan::Operator> & holoscan::ops::OperatorRunner::op() constconst std::shared_ptr<holoscan::Operator> & holoscan::ops::OperatorRunner::op() const

Get the operator.

Returns: The shared pointer to the operator.

push_input

holoscan::expected<void, holoscan::RuntimeError> holoscan::ops::OperatorRunner::push_input(holoscan::expected<void, holoscan::RuntimeError> holoscan::ops::OperatorRunner::push_input(
const std::string &port_name,
nvidia::gxf::Entity &entity
)

Push data to the specified input port of the operator.

This method takes a GXF entity and pushes it to the input port identified by port_name. The entity will be available to the operator during its next compute cycle.

Returns: A holoscan::expected containing either:void if successful A holoscan::RuntimeError if the input port is not found

Parameters

port_name
const std::string &

The name of the input port.

entity
nvidia::gxf::Entity &

The entity to push to the input port.

run

void holoscan::ops::OperatorRunner::run()

Executes one compute cycle of the operator.

Internally, it calls the compute() method of the operator via the GXFWrapper’s tick() method.

pop_output

holoscan::expected<holoscan::gxf::Entity, holoscan::RuntimeError> holoscan::ops::OperatorRunner::pop_output(holoscan::expected<holoscan::gxf::Entity, holoscan::RuntimeError> holoscan::ops::OperatorRunner::pop_output(holoscan::expected<holoscan::gxf::Entity, holoscan::RuntimeError> holoscan::ops::OperatorRunner::pop_output(
const std::string &port_name
)

Retrieves and removes an entity from the specified output port.

This method retrieves and removes an entity from the output port identified by port_name. The entity is removed from the output port and returned.

Returns: The entity popped from the output port.

Parameters

port_name
const std::string &

The name of the output port.

populate_tensor_map

bool holoscan::ops::OperatorRunner::populate_tensor_map(
const holoscan::gxf::Entity &gxf_entity,
holoscan::TensorMap &tensor_map
)

handle_message_output

template <typename DataT>
holoscan::expected<DataT, holoscan::RuntimeError> holoscan::ops::OperatorRunner::handle_message_output(holoscan::expected<DataT, holoscan::RuntimeError> holoscan::ops::OperatorRunner::handle_message_output(
const nvidia::gxf::Entity &entity,
const std::string &port_name
)

handle_tensor_map_output

holoscan::expected<holoscan::TensorMap, holoscan::RuntimeError> holoscan::ops::OperatorRunner::handle_tensor_map_output(holoscan::expected<holoscan::TensorMap, holoscan::RuntimeError> holoscan::ops::OperatorRunner::handle_tensor_map_output(holoscan::expected<holoscan::TensorMap, holoscan::RuntimeError> holoscan::ops::OperatorRunner::handle_tensor_map_output(
const holoscan::gxf::Entity &entity,
const std::string &port_name
)

create_error

template <typename... Args>
holoscan::unexpected<holoscan::RuntimeError> holoscan::ops::OperatorRunner::create_error(holoscan::unexpected<holoscan::RuntimeError> holoscan::ops::OperatorRunner::create_error(
holoscan::ErrorCode code,
const char *format,
Args &&... args
)

Member variables

NameTypeDescription
op_std::shared_ptr< holoscan::Operator >The operator to run.
gxf_context_void *The GXF context to interact with the operator.
gxf_wrapper_holoscan::gxf::GXFWrapper *The underlying GXFWrapper to run the operator.
async_condition_std::shared_ptr< holoscan::AsynchronousCondition >The asynchronous condition to block the operator execution.
double_buffer_receivers_std::unordered_map< std::string, nvidia::gxf::DoubleBufferReceiver * >Double buffer receivers corresponding to the operator’s input ports (input port name -> receiver).
double_buffer_transmitters_std::unordered_map< std::string, nvidia::gxf::DoubleBufferTransmitter * >Double buffer transmitters corresponding to the operator’s output ports (output port name -> transmitter).