cpp-common/bt2: add component class creation methods
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 16 Feb 2024 20:00:59 +0000 (15:00 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Mon, 19 Feb 2024 18:10:15 +0000 (13:10 -0500)
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 <simon.marchi@efficios.com>
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11817

src/cpp-common/bt2/component-class-dev.hpp
src/cpp-common/bt2/component-class.hpp

index 1174140f1118b9f21bac3452c86641cab7fc76a9..9e2969ecc4ac801d47057aada0e9cc8ee26e6741 100644 (file)
@@ -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 <typename UserComponentT, typename CompClsBridgeT, typename LibSpecCompClsPtrT,
+          typename AsCompClsFuncT, typename SetInitMethodFuncT, typename SetFinalizeMethodFuncT,
+          typename SetGetSupportedMipVersionsMethodFuncT, typename SetQueryMethodFuncT>
+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 <typename MsgIterClsBridgeT>
+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 <typename UserComponentT>
+bt_component_class_source *createSourceCompCls()
+{
+    static_assert(
+        std::is_base_of<UserSourceComponent<
+                            UserComponentT, typename UserComponentT::MessageIterator,
+                            typename UserComponentT::InitData, typename UserComponentT::QueryData>,
+                        UserComponentT>::value,
+        "`UserComponentT` inherits `UserSourceComponent`");
+
+    using CompClsBridge = internal::SrcCompClsBridge<UserComponentT>;
+    using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
+
+    const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
+    const auto libCompClsPtr =
+        bt_component_class_source_create(UserComponentT::name, libMsgIterClsPtr);
+
+    bt_message_iterator_class_put_ref(libMsgIterClsPtr);
+
+    if (!libCompClsPtr) {
+        throw MemoryError {};
+    }
+
+    setCompClsCommonProps<UserComponentT, CompClsBridge>(
+        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 <typename UserComponentT>
+bt_component_class_filter *createFilterCompCls()
+{
+    static_assert(
+        std::is_base_of<UserFilterComponent<
+                            UserComponentT, typename UserComponentT::MessageIterator,
+                            typename UserComponentT::InitData, typename UserComponentT::QueryData>,
+                        UserComponentT>::value,
+        "`UserComponentT` inherits `UserFilterComponent`");
+
+    using CompClsBridge = internal::FltCompClsBridge<UserComponentT>;
+    using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
+
+    const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
+    const auto libCompClsPtr =
+        bt_component_class_filter_create(UserComponentT::name, libMsgIterClsPtr);
+
+    bt_message_iterator_class_put_ref(libMsgIterClsPtr);
+
+    if (!libCompClsPtr) {
+        throw MemoryError {};
+    }
+
+    setCompClsCommonProps<UserComponentT, CompClsBridge>(
+        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 <typename UserComponentT>
+bt_component_class_sink *createSinkCompCls()
+{
+    static_assert(
+        std::is_base_of<UserSinkComponent<UserComponentT, typename UserComponentT::InitData,
+                                          typename UserComponentT::QueryData>,
+                        UserComponentT>::value,
+        "`UserComponentT` inherits `UserSinkComponent`");
+
+    using CompClsBridge = internal::SinkCompClsBridge<UserComponentT>;
+
+    const auto libCompClsPtr =
+        bt_component_class_sink_create(UserComponentT::name, CompClsBridge::consume);
+
+    if (!libCompClsPtr) {
+        throw MemoryError {};
+    }
+
+    setCompClsCommonProps<UserComponentT, CompClsBridge>(
+        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 */
index 51f7f470b736245c373b34d5e8e5e49f43a94481..efee3f43cfec81c5544089a4c3a010d70ed79047 100644 (file)
@@ -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 <typename UserComponentT>
+    static CommonSourceComponentClass<LibObjT>::Shared create()
+    {
+        return CommonSourceComponentClass::Shared::createWithoutRef(
+            internal::createSourceCompCls<UserComponentT>());
+    }
+
     bt2c::CStringView name() const noexcept
     {
         return this->_constComponentClass().name();
@@ -279,6 +287,13 @@ public:
         return *this;
     }
 
+    template <typename UserComponentT>
+    static CommonFilterComponentClass<LibObjT>::Shared create()
+    {
+        return CommonFilterComponentClass::Shared::createWithoutRef(
+            internal::createFilterCompCls<UserComponentT>());
+    }
+
     bt2c::CStringView name() const noexcept
     {
         return this->_constComponentClass().name();
@@ -383,6 +398,13 @@ public:
         return *this;
     }
 
+    template <typename UserComponentT>
+    static CommonSinkComponentClass<LibObjT>::Shared create()
+    {
+        return CommonSinkComponentClass::Shared::createWithoutRef(
+            internal::createSinkCompCls<UserComponentT>());
+    }
+
     bt2c::CStringView name() const noexcept
     {
         return this->_constComponentClass().name();
This page took 0.027827 seconds and 4 git commands to generate.