From ee137c4e4bca141db9d2cca32e3ac9b42c1ac52b Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Fri, 16 Feb 2024 15:00:59 -0500 Subject: [PATCH] cpp-common/bt2: add component class creation methods Add `create()` methods to `CommonSourceComponentClass`, `CommonFilterComponentClass` and `CommonSinkComponentClass`, allowing the user to create component classes at run time from some class that derives from `UserSourceComponent`, `UserFilterComponent` and `UserSinkComponent`. The user component class (`UserComponentT`) must provide a static member `name` of type `const char *`. It can also provide static members named `description` and `help`, also of type `const char *`. Change-Id: I3bd550fd90a2a75d8154d29d00bf0bf4f9b1fd3e Signed-off-by: Simon Marchi Signed-off-by: Philippe Proulx Reviewed-on: https://review.lttng.org/c/babeltrace/+/11817 --- src/cpp-common/bt2/component-class-dev.hpp | 236 +++++++++++++++++++++ src/cpp-common/bt2/component-class.hpp | 22 ++ 2 files changed, 258 insertions(+) diff --git a/src/cpp-common/bt2/component-class-dev.hpp b/src/cpp-common/bt2/component-class-dev.hpp index 1174140f..9e2969ec 100644 --- a/src/cpp-common/bt2/component-class-dev.hpp +++ b/src/cpp-common/bt2/component-class-dev.hpp @@ -16,6 +16,7 @@ #include "cpp-common/vendor/fmt/core.h" #include "exc.hpp" +#include "internal/comp-cls-bridge.hpp" #include "private-query-executor.hpp" #include "self-component-port.hpp" @@ -41,6 +42,9 @@ public: using InitData = InitDataT; using QueryData = QueryDataT; + static constexpr auto description = nullptr; + static constexpr auto help = nullptr; + protected: explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) : _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp} @@ -77,6 +81,13 @@ private: /* * Base class of a user source component `UserComponentT` (CRTP). * + * `UserComponentT` must define a static member `name` of type + * `const char *` to provide the name of the component class. + * + * `UserComponentT` may define the static members `description` and/or + * `help` of type `const char *` to provide the description and/or help + * of the component class. + * * UserComponentT::UserComponentT() must accept, in this order: * * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward @@ -173,6 +184,13 @@ protected: /* * Base class of a user filter component `UserComponentT` (CRTP). * + * `UserComponentT` must define a static member `name` of type + * `const char *` to provide the name of the component class. + * + * `UserComponentT` may define the static members `description` and/or + * `help` of type `const char *` to provide the description and/or help + * of the component class. + * * UserComponentT::UserComponentT() must accept, in this order: * * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward @@ -297,6 +315,13 @@ protected: /* * Base class of a user sink component `UserComponentT` (CRTP). * + * `UserComponentT` must define a static member `name` of type + * `const char *` to provide the name of the component class. + * + * `UserComponentT` may define the static members `description` and/or + * `help` of type `const char *` to provide the description and/or help + * of the component class. + * * UserComponentT::UserComponentT() must accept, in this order: * * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward @@ -627,6 +652,217 @@ protected: bt2c::Logger _mLogger; }; +namespace internal { + +template +void setCompClsCommonProps( + LibSpecCompClsPtrT * const libSpecCompClsPtr, AsCompClsFuncT&& asCompClsFunc, + SetInitMethodFuncT&& setInitMethodFunc, SetFinalizeMethodFuncT&& setFinalizeMethodFunc, + SetGetSupportedMipVersionsMethodFuncT&& setGetSupportedMipVersionsMethodFunc, + SetQueryMethodFuncT&& setQueryMethodFunc) +{ + const auto libCompClsPtr = asCompClsFunc(libSpecCompClsPtr); + + if (UserComponentT::description != nullptr) { + const auto status = + bt_component_class_set_description(libCompClsPtr, UserComponentT::description); + + if (status == BT_COMPONENT_CLASS_SET_DESCRIPTION_STATUS_MEMORY_ERROR) { + throw MemoryError {}; + } + } + + if (UserComponentT::help != nullptr) { + const auto status = bt_component_class_set_help(libCompClsPtr, UserComponentT::help); + + if (status == BT_COMPONENT_CLASS_SET_HELP_STATUS_MEMORY_ERROR) { + throw MemoryError {}; + } + } + + { + const auto status = setInitMethodFunc(libSpecCompClsPtr, CompClsBridgeT::init); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = setFinalizeMethodFunc(libSpecCompClsPtr, CompClsBridgeT::finalize); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = setGetSupportedMipVersionsMethodFunc( + libSpecCompClsPtr, CompClsBridgeT::getSupportedMipVersions); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = setQueryMethodFunc(libSpecCompClsPtr, CompClsBridgeT::query); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } +} + +template +bt_message_iterator_class *createLibMsgIterCls() +{ + const auto libMsgIterClsPtr = bt_message_iterator_class_create(MsgIterClsBridgeT::next); + + if (!libMsgIterClsPtr) { + throw MemoryError {}; + } + + { + const auto status = bt_message_iterator_class_set_initialize_method( + libMsgIterClsPtr, MsgIterClsBridgeT::init); + + BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = bt_message_iterator_class_set_finalize_method( + libMsgIterClsPtr, MsgIterClsBridgeT::finalize); + + BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK); + } + + return libMsgIterClsPtr; +} + +template +bt_component_class_source *createSourceCompCls() +{ + static_assert( + std::is_base_of, + UserComponentT>::value, + "`UserComponentT` inherits `UserSourceComponent`"); + + using CompClsBridge = internal::SrcCompClsBridge; + using MsgIterClsBridge = internal::MsgIterClsBridge; + + const auto libMsgIterClsPtr = createLibMsgIterCls(); + const auto libCompClsPtr = + bt_component_class_source_create(UserComponentT::name, libMsgIterClsPtr); + + bt_message_iterator_class_put_ref(libMsgIterClsPtr); + + if (!libCompClsPtr) { + throw MemoryError {}; + } + + setCompClsCommonProps( + libCompClsPtr, bt_component_class_source_as_component_class, + bt_component_class_source_set_initialize_method, + bt_component_class_source_set_finalize_method, + bt_component_class_source_set_get_supported_mip_versions_method, + bt_component_class_source_set_query_method); + + { + const auto status = bt_component_class_source_set_output_port_connected_method( + libCompClsPtr, CompClsBridge::outputPortConnected); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + return libCompClsPtr; +} + +template +bt_component_class_filter *createFilterCompCls() +{ + static_assert( + std::is_base_of, + UserComponentT>::value, + "`UserComponentT` inherits `UserFilterComponent`"); + + using CompClsBridge = internal::FltCompClsBridge; + using MsgIterClsBridge = internal::MsgIterClsBridge; + + const auto libMsgIterClsPtr = createLibMsgIterCls(); + const auto libCompClsPtr = + bt_component_class_filter_create(UserComponentT::name, libMsgIterClsPtr); + + bt_message_iterator_class_put_ref(libMsgIterClsPtr); + + if (!libCompClsPtr) { + throw MemoryError {}; + } + + setCompClsCommonProps( + libCompClsPtr, bt_component_class_filter_as_component_class, + bt_component_class_filter_set_initialize_method, + bt_component_class_filter_set_finalize_method, + bt_component_class_filter_set_get_supported_mip_versions_method, + bt_component_class_filter_set_query_method); + + { + const auto status = bt_component_class_filter_set_input_port_connected_method( + libCompClsPtr, CompClsBridge::inputPortConnected); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = bt_component_class_filter_set_output_port_connected_method( + libCompClsPtr, CompClsBridge::outputPortConnected); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + return libCompClsPtr; +} + +template +bt_component_class_sink *createSinkCompCls() +{ + static_assert( + std::is_base_of, + UserComponentT>::value, + "`UserComponentT` inherits `UserSinkComponent`"); + + using CompClsBridge = internal::SinkCompClsBridge; + + const auto libCompClsPtr = + bt_component_class_sink_create(UserComponentT::name, CompClsBridge::consume); + + if (!libCompClsPtr) { + throw MemoryError {}; + } + + setCompClsCommonProps( + libCompClsPtr, bt_component_class_sink_as_component_class, + bt_component_class_sink_set_initialize_method, bt_component_class_sink_set_finalize_method, + bt_component_class_sink_set_get_supported_mip_versions_method, + bt_component_class_sink_set_query_method); + + { + const auto status = bt_component_class_sink_set_graph_is_configured_method( + libCompClsPtr, CompClsBridge::graphIsConfigured); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = bt_component_class_sink_set_input_port_connected_method( + libCompClsPtr, CompClsBridge::inputPortConnected); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + return libCompClsPtr; +} + +} /* namespace internal */ } /* namespace bt2 */ #endif /* BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP */ diff --git a/src/cpp-common/bt2/component-class.hpp b/src/cpp-common/bt2/component-class.hpp index 51f7f470..efee3f43 100644 --- a/src/cpp-common/bt2/component-class.hpp +++ b/src/cpp-common/bt2/component-class.hpp @@ -12,6 +12,7 @@ #include "cpp-common/bt2c/c-string-view.hpp" #include "borrowed-object.hpp" +#include "component-class-dev.hpp" #include "shared-object.hpp" namespace bt2 { @@ -175,6 +176,13 @@ public: return *this; } + template + static CommonSourceComponentClass::Shared create() + { + return CommonSourceComponentClass::Shared::createWithoutRef( + internal::createSourceCompCls()); + } + bt2c::CStringView name() const noexcept { return this->_constComponentClass().name(); @@ -279,6 +287,13 @@ public: return *this; } + template + static CommonFilterComponentClass::Shared create() + { + return CommonFilterComponentClass::Shared::createWithoutRef( + internal::createFilterCompCls()); + } + bt2c::CStringView name() const noexcept { return this->_constComponentClass().name(); @@ -383,6 +398,13 @@ public: return *this; } + template + static CommonSinkComponentClass::Shared create() + { + return CommonSinkComponentClass::Shared::createWithoutRef( + internal::createSinkCompCls()); + } + bt2c::CStringView name() const noexcept { return this->_constComponentClass().name(); -- 2.34.1