Program Listing for File io_context.hpp

Return to documentation for file (include/holoscan/core/io_context.hpp)

Copy
Copied!
            

/* * SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HOLOSCAN_CORE_IO_CONTEXT_HPP #define HOLOSCAN_CORE_IO_CONTEXT_HPP #include <any> #include <memory> #include <string> #include <typeinfo> #include <unordered_map> #include <utility> #include <vector> #include <gxf/core/expected.hpp> #include "./common.hpp" #include "./gxf/entity.hpp" #include "./message.hpp" #include "./operator.hpp" #include "./type_traits.hpp" namespace holoscan { class InputContext { public: InputContext(Operator* op, std::unordered_map<std::string, std::unique_ptr<IOSpec>>& inputs) : op_(op), inputs_(inputs) {} explicit InputContext(Operator* op) : op_(op), inputs_(op->spec()->inputs()) {} Operator* op() const { return op_; } std::unordered_map<std::string, std::unique_ptr<IOSpec>>& inputs() const { return inputs_; } template <typename DataT, typename = std::enable_if_t< !holoscan::is_vector_v<DataT> && !holoscan::is_one_of_v<DataT, holoscan::gxf::Entity, std::any>>> std::shared_ptr<DataT> receive(const char* name = nullptr) { auto value = receive_impl(name); try { return std::any_cast<std::shared_ptr<DataT>>(value); } catch (const std::bad_any_cast& e) { HOLOSCAN_LOG_ERROR( "Unable to cast the received data to the specified type (std::shared_ptr<" "DataT>): {}", e.what()); return nullptr; } } template <typename DataT, typename = std::enable_if_t<holoscan::is_one_of_v<DataT, holoscan::gxf::Entity>>> DataT receive(const char* name) { auto value = receive_impl(name); try { return std::any_cast<holoscan::gxf::Entity>(value); } catch (const std::bad_any_cast& e) { throw std::runtime_error( fmt::format("Unable to cast the received data to the specified type (holoscan::gxf::" "Entity): {}", e.what())); } } template <typename DataT, typename = std::enable_if_t<holoscan::is_one_of_v<DataT, std::any>>> std::any receive(const char* name) { auto value = receive_impl(name); return value; } template <typename DataT, typename = std::enable_if_t< holoscan::is_vector_v<DataT> && !holoscan::is_one_of_v<typename holoscan::type_info<DataT>::element_type, holoscan::gxf::Entity, std::any>>> std::vector<std::shared_ptr<typename holoscan::type_info<DataT>::element_type>> receive( const char* name) { using DataT_ElementT = typename holoscan::type_info<DataT>::element_type; std::vector<std::shared_ptr<DataT_ElementT>> input_vector; auto& params = op_->spec()->params(); auto it = params.find(std::string(name)); if (it == params.end()) { HOLOSCAN_LOG_ERROR( "Unable to find input parameter with type 'std::vector<IOSpec*>' and name '{}'", name); return input_vector; } auto& param_wrapper = it->second; auto& arg_type = param_wrapper.arg_type(); if ((arg_type.element_type() != ArgElementType::kIOSpec) || (arg_type.container_type() != ArgContainerType::kVector)) { HOLOSCAN_LOG_ERROR("Input parameter with name {} is not of type 'std::vector<IOSpec*>'", name); return input_vector; } std::any& any_param = param_wrapper.value(); // Note that the type of any_param is Parameter *, not Parameter . auto& param = *std::any_cast<Parameter<std::vector<IOSpec*>>*>(any_param); int num_inputs = param.get().size(); input_vector.reserve(num_inputs); for (int index = 0; index < num_inputs; ++index) { // Check if the input name points to the parameter name of the operator, // and the parameter type is 'std::vector '. // In other words, find if there is a receiver with a specific label // (' : '. e.g, 'receivers:0') to return an object with // 'std::vector ' type. auto value = receive_impl(fmt::format("{}:{}", name, index).c_str(), true); try { auto casted_value = std::any_cast<std::shared_ptr<DataT_ElementT>>(value); input_vector.push_back(std::move(casted_value)); } catch (const std::bad_any_cast& e) { HOLOSCAN_LOG_ERROR( "Unable to receive input (std::vector<std::shared_ptr<DataT>>) with name " "'{}:{}' ({}). Skipping adding to the vector.", name, index, e.what()); } } return input_vector; } template <typename DataT, typename = std::enable_if_t< holoscan::is_vector_v<DataT> && holoscan::is_one_of_v<typename holoscan::type_info<DataT>::element_type, holoscan::gxf::Entity>>> std::vector<holoscan::gxf::Entity> receive(const char* name) { std::vector<holoscan::gxf::Entity> input_vector; auto& params = op_->spec()->params(); auto it = params.find(std::string(name)); if (it == params.end()) { HOLOSCAN_LOG_ERROR( "Unable to find input parameter with type 'std::vector<IOSpec*>' and name '{}'", name); return input_vector; } auto& param_wrapper = it->second; auto& arg_type = param_wrapper.arg_type(); if ((arg_type.element_type() != ArgElementType::kIOSpec) || (arg_type.container_type() != ArgContainerType::kVector)) { HOLOSCAN_LOG_ERROR("Input parameter with name {} is not of type 'std::vector<IOSpec*>'", name); return input_vector; } std::any& any_param = param_wrapper.value(); // Note that the type of any_param is Parameter *, not Parameter . auto& param = *std::any_cast<Parameter<std::vector<IOSpec*>>*>(any_param); int num_inputs = param.get().size(); input_vector.reserve(num_inputs); for (int index = 0; index < num_inputs; ++index) { // Check if the input name points to the parameter name of the operator, // and the parameter type is 'std::vector '. // In other words, find if there is a receiver with a specific label // (' : '. e.g, 'receivers:0') to return an object with // 'std::vector ' type. auto value = receive_impl(fmt::format("{}:{}", name, index).c_str(), true); try { auto casted_value = std::any_cast<holoscan::gxf::Entity>(value); input_vector.push_back(std::move(casted_value)); } catch (const std::bad_any_cast& e) { HOLOSCAN_LOG_ERROR( "Unable to receive input (std::vector<holoscan::gxf::Entity>) " "with name " "'{}:{}' ({}). Skipping adding to the vector.", name, index, e.what()); } } return input_vector; } template <typename DataT, typename = std::enable_if_t< holoscan::is_vector_v<DataT> && holoscan::is_one_of_v<typename holoscan::type_info<DataT>::element_type, std::any>>> std::vector<std::any> receive(const char* name) { std::vector<std::any> input_vector; auto& params = op_->spec()->params(); auto it = params.find(std::string(name)); if (it == params.end()) { HOLOSCAN_LOG_ERROR( "Unable to find input parameter with type 'std::vector<IOSpec*>' and name '{}'", name); return input_vector; } auto& param_wrapper = it->second; auto& arg_type = param_wrapper.arg_type(); if ((arg_type.element_type() != ArgElementType::kIOSpec) || (arg_type.container_type() != ArgContainerType::kVector)) { HOLOSCAN_LOG_ERROR("Input parameter with name {} is not of type 'std::vector<IOSpec*>'", name); return input_vector; } std::any& any_param = param_wrapper.value(); // Note that the type of any_param is Parameter *, not Parameter . auto& param = *std::any_cast<Parameter<std::vector<IOSpec*>>*>(any_param); int num_inputs = param.get().size(); input_vector.reserve(num_inputs); for (int index = 0; index < num_inputs; ++index) { // Check if the input name points to the parameter name of the operator, // and the parameter type is 'std::vector '. // In other words, find if there is a receiver with a specific label // (' : '. e.g, 'receivers:0') to return an object with // 'std::vector ' type. auto value = receive_impl(fmt::format("{}:{}", name, index).c_str(), true); input_vector.push_back(std::move(value)); } return input_vector; } protected: virtual std::any receive_impl(const char* name = nullptr, bool no_error_message = false) { (void)name; (void)no_error_message; return nullptr; } Operator* op_ = nullptr; std::unordered_map<std::string, std::unique_ptr<IOSpec>>& inputs_; }; class OutputContext { public: OutputContext(Operator* op, std::unordered_map<std::string, std::unique_ptr<IOSpec>>& outputs) : op_(op), outputs_(outputs) {} Operator* op() const { return op_; } std::unordered_map<std::string, std::unique_ptr<IOSpec>>& outputs() const { return outputs_; } explicit OutputContext(Operator* op) : op_(op), outputs_(op->spec()->outputs()) {} enum class OutputType { kSharedPointer, kGXFEntity, }; template <typename DataT> void emit(std::shared_ptr<DataT>& data, const char* name = nullptr) { emit_impl(data, name); } template <typename DataT, typename = std::enable_if_t<std::is_same_v<holoscan::gxf::Entity, std::decay_t<DataT>>>> void emit(DataT& data, const char* name = nullptr) { emit_impl(data, name, OutputType::kGXFEntity); } protected: virtual void emit_impl(std::any data, const char* name = nullptr, OutputType out_type = OutputType::kSharedPointer) { (void)data; (void)name; (void)out_type; } Operator* op_ = nullptr; std::unordered_map<std::string, std::unique_ptr<IOSpec>>& outputs_; }; } // namespace holoscan #endif/* HOLOSCAN_CORE_IO_CONTEXT_HPP */

© Copyright 2022, NVIDIA. Last updated on Jun 28, 2023.