2 * Copyright (c) 2024 EfficiOS, Inc.
4 * SPDX-License-Identifier: MIT
7 #ifndef BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP
14 #include "cpp-common/bt2c/c-string-view.hpp"
15 #include "cpp-common/bt2c/logging.hpp"
16 #include "cpp-common/vendor/fmt/core.h"
19 #include "internal/comp-cls-bridge.hpp"
20 #include "private-query-executor.hpp"
21 #include "self-component-port.hpp"
25 template <typename UserMessageIteratorT, typename UserComponentT>
26 class UserMessageIterator;
29 * Base class of any user component.
31 * See the specific `bt2::UserSourceComponent`,
32 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
34 template <typename SelfCompT, typename InitDataT, typename QueryDataT>
37 /* Give a related message iterator access to this logger */
38 template <typename, typename>
39 friend class UserMessageIterator;
42 using InitData = InitDataT;
43 using QueryData = QueryDataT;
45 static constexpr auto description = nullptr;
46 static constexpr auto help = nullptr;
49 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
50 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
54 bt2c::CStringView _name() const noexcept
56 return _mSelfComp.name();
59 LoggingLevel _loggingLevel() const noexcept
61 return _mSelfComp.loggingLevel();
64 std::uint64_t _graphMipVersion() const noexcept
66 return _mSelfComp.graphMipVersion();
69 SelfCompT _selfComp() noexcept
74 bt2c::Logger _mLogger;
81 * Base class of a user source component `UserComponentT` (CRTP).
83 * `UserComponentT` must define a static member `name` of type
84 * `const char *` to provide the name of the component class.
86 * `UserComponentT` may define the static members `description` and/or
87 * `help` of type `const char *` to provide the description and/or help
88 * of the component class.
90 * UserComponentT::UserComponentT() must accept, in this order:
92 * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward
93 * to bt2::UserSourceComponent::UserSourceComponent().
95 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
97 * 3. An `InitDataT *` parameter (the initialization method data).
99 * `UserMessageIteratorT`, the message iterator class to use, must inherit
100 * `UserMessageIterator`.
102 * UserComponentT::_query() receives a query method data pointer of type
103 * `QueryDataT *` as its last parameter.
105 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
106 typename QueryDataT = void>
107 class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT, QueryDataT>
109 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
110 UserMessageIteratorT>::value,
111 "`UserMessageIteratorT` inherits `UserMessageIterator`");
114 using MessageIterator = UserMessageIteratorT;
117 using _OutputPorts = SelfSourceComponent::OutputPorts;
119 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
120 UserComponent<SelfSourceComponent, InitDataT, QueryDataT> {selfComp, logTag}
125 static Value::Shared query(const SelfComponentClass selfCompCls,
126 const PrivateQueryExecutor privQueryExec,
127 const bt2c::CStringView obj, const ConstValue params,
128 QueryDataT * const data)
130 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
133 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
134 const ConstValue params, const LoggingLevel loggingLevel,
135 const UnsignedIntegerRangeSet ranges)
137 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
140 void outputPortConnected(const SelfComponentOutputPort outputPort,
141 const ConstInputPort inputPort)
143 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
148 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
149 ConstValue, QueryDataT *)
151 throw UnknownObject {};
155 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
156 const UnsignedIntegerRangeSet ranges)
158 ranges.addRange(0, 0);
162 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
166 template <typename DataT>
167 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
169 return this->_selfComp().addOutputPort(name, data);
172 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
174 return this->_selfComp().addOutputPort(name);
177 _OutputPorts _outputPorts() noexcept
179 return this->_selfComp().outputPorts();
184 * Base class of a user filter component `UserComponentT` (CRTP).
186 * `UserComponentT` must define a static member `name` of type
187 * `const char *` to provide the name of the component class.
189 * `UserComponentT` may define the static members `description` and/or
190 * `help` of type `const char *` to provide the description and/or help
191 * of the component class.
193 * UserComponentT::UserComponentT() must accept, in this order:
195 * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward
196 * to bt2::UserFilterComponent::UserFilterComponent().
198 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
200 * 3. An `InitDataT *` parameter (the initialization method data).
202 * `UserMessageIteratorT`, the message iterator class to use, must inherit
203 * `UserMessageIterator`.
205 * UserComponentT::_query() receives a query method data pointer of type
206 * `QueryDataT *` as its last parameter.
208 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
209 typename QueryDataT = void>
210 class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT, QueryDataT>
212 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
213 UserMessageIteratorT>::value,
214 "`UserMessageIteratorT` inherits `UserMessageIterator`");
217 using MessageIterator = UserMessageIteratorT;
220 using _InputPorts = SelfFilterComponent::InputPorts;
221 using _OutputPorts = SelfFilterComponent::OutputPorts;
223 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
224 UserComponent<SelfFilterComponent, InitDataT, QueryDataT> {selfComp, logTag}
229 static Value::Shared query(const SelfComponentClass selfCompCls,
230 const PrivateQueryExecutor privQueryExec,
231 const bt2c::CStringView obj, const ConstValue params,
232 QueryDataT * const data)
234 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
237 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
238 const ConstValue params, const LoggingLevel loggingLevel,
239 const UnsignedIntegerRangeSet ranges)
241 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
244 void inputPortConnected(const SelfComponentInputPort inputPort,
245 const ConstOutputPort outputPort)
247 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
250 void outputPortConnected(const SelfComponentOutputPort outputPort,
251 const ConstInputPort inputPort)
253 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
258 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
259 ConstValue, QueryDataT *)
261 throw UnknownObject {};
265 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
266 const UnsignedIntegerRangeSet ranges)
268 ranges.addRange(0, 0);
272 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
277 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
281 template <typename DataT>
282 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
284 return this->_selfComp().addInputPort(name, data);
287 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
289 return this->_selfComp().addInputPort(name);
292 _InputPorts _inputPorts() noexcept
294 return this->_selfComp().inputPorts();
297 template <typename DataT>
298 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
300 return this->_selfComp().addOutputPort(name, data);
303 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
305 return this->_selfComp().addOutputPort(name);
308 _OutputPorts _outputPorts() noexcept
310 return this->_selfComp().outputPorts();
315 * Base class of a user sink component `UserComponentT` (CRTP).
317 * `UserComponentT` must define a static member `name` of type
318 * `const char *` to provide the name of the component class.
320 * `UserComponentT` may define the static members `description` and/or
321 * `help` of type `const char *` to provide the description and/or help
322 * of the component class.
324 * UserComponentT::UserComponentT() must accept, in this order:
326 * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward
327 * to bt2::UserSinkComponent::UserSinkComponent().
329 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
331 * 3. An `InitDataT *` parameter (the initialization method data).
333 * `UserComponentT` must implement:
337 * This method returns `true` if the sink component still needs to
338 * consume, or `false` if it's finished.
340 * UserComponentT::_query() receives a query method data pointer of type
341 * `QueryDataT *` as its last parameter.
344 template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void>
345 class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT>
348 using _InputPorts = SelfSinkComponent::InputPorts;
350 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
351 UserComponent<SelfSinkComponent, InitDataT, QueryDataT> {selfComp, logTag}
356 static Value::Shared query(const SelfComponentClass selfCompCls,
357 const PrivateQueryExecutor privQueryExec,
358 const bt2c::CStringView obj, const ConstValue params,
359 QueryDataT * const data)
361 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
364 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
365 const ConstValue params, const LoggingLevel loggingLevel,
366 const UnsignedIntegerRangeSet ranges)
368 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
371 void graphIsConfigured()
373 static_cast<UserComponentT&>(*this)._graphIsConfigured();
376 void inputPortConnected(const SelfComponentInputPort inputPort,
377 const ConstOutputPort outputPort)
379 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
384 return static_cast<UserComponentT&>(*this)._consume();
389 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
390 ConstValue, QueryDataT *)
392 throw UnknownObject {};
396 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
397 const UnsignedIntegerRangeSet ranges)
399 ranges.addRange(0, 0);
403 void _graphIsConfigured()
408 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
412 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
414 return this->_selfComp().createMessageIterator(port);
417 template <typename DataT>
418 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
420 return this->_selfComp().addInputPort(name, data);
423 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
425 return this->_selfComp().addInputPort(name);
428 _InputPorts _inputPorts() noexcept
430 return this->_selfComp().inputPorts();
435 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
436 * of which the parent user component class is `UserComponentT`.
438 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
439 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
440 * bt2::UserMessageIterator::UserMessageIterator().
442 * The public next() method below (called by the bridge) implements the
443 * very common pattern of appending messages into the output array, and,
446 * If it catches a `bt2::TryAgain` exception:
447 * If the message array isn't empty, transform this into a success
452 * If it catches an error:
453 * If the message array isn't empty, transform this into a success
454 * (don't throw), but save the error of the current thread and the
455 * type of error to throw the next time the user calls next().
459 * `UserMessageIteratorT` must implement:
461 * void _next(bt2::ConstMessageArray& messages);
463 * This method fills `messages` with at most `messages.capacity()`
464 * messages and may throw `bt2::TryAgain` or a valid error whenever.
465 * Leaving an empty `messages` means the end of iteration.
467 template <typename UserMessageIteratorT, typename UserComponentT>
468 class UserMessageIterator
471 /* Type of `_mExcToThrowType` */
472 enum class _ExcToThrowType
480 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
481 const std::string& logTagSuffix) :
482 _mSelfMsgIter {selfMsgIter},
483 _mLogger {selfMsgIter,
484 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
489 void next(ConstMessageArray& messages)
491 /* Any saved error? Now is the time to throw */
492 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
493 /* Move `_mSavedLibError`, if any, as current thread error */
494 if (_mSavedLibError) {
495 bt_current_thread_move_error(_mSavedLibError.release());
498 /* Throw the corresponding exception */
499 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
502 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
503 throw MemoryError {};
508 * When catching some exception below, if our message array
509 * isn't empty, then return immediately before throwing to
510 * provide those messages to downstream.
512 * When catching an error, also save the current thread error,
513 * if any, so that we can restore it later (see the beginning of
516 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
519 this->_userObj()._next(messages);
521 /* We're done: everything below is exception handling */
523 } catch (const TryAgain&) {
524 if (messages.isEmpty()) {
527 } catch (const std::bad_alloc&) {
528 if (messages.isEmpty()) {
532 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
533 } catch (const Error&) {
534 if (messages.isEmpty()) {
538 _mExcToThrowType = _ExcToThrowType::ERROR;
541 if (_mExcToThrowType != _ExcToThrowType::NONE) {
543 "An error occurred, but there are {} messages to return: delaying the error reporting.",
545 BT_ASSERT(!_mSavedLibError);
546 _mSavedLibError.reset(bt_current_thread_take_error());
550 bool canSeekBeginning()
553 return this->_userObj()._canSeekBeginning();
559 return this->_userObj()._seekBeginning();
562 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
565 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
568 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
571 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
576 bool _canSeekBeginning() noexcept
582 void _seekBeginning() noexcept
587 bool _canSeekNsFromOrigin(std::int64_t) noexcept
593 void _seekNsFromOrigin(std::int64_t) noexcept
597 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
599 return _mSelfMsgIter.createMessageIterator(port);
602 StreamBeginningMessage::Shared _createStreamBeginningMessage(const ConstStream stream) const
604 return _mSelfMsgIter.createStreamBeginningMessage(stream);
607 StreamEndMessage::Shared _createStreamEndMessage(const ConstStream stream) const
609 return _mSelfMsgIter.createStreamEndMessage(stream);
612 EventMessage::Shared _createEventMessage(const ConstEventClass eventCls,
613 const ConstStream stream) const
615 return _mSelfMsgIter.createEventMessage(eventCls, stream);
618 EventMessage::Shared _createEventMessage(const ConstEventClass eventCls,
619 const ConstStream stream,
620 const std::uint64_t clockSnapshotValue) const
622 return _mSelfMsgIter.createEventMessage(eventCls, stream, clockSnapshotValue);
625 EventMessage::Shared _createEventMessage(const ConstEventClass eventCls,
626 const ConstPacket packet) const
628 return _mSelfMsgIter.createEventMessage(eventCls, packet);
631 EventMessage::Shared _createEventMessage(const ConstEventClass eventCls,
632 const ConstPacket packet,
633 const std::uint64_t clockSnapshotValue) const
635 return _mSelfMsgIter.createEventMessage(eventCls, packet, clockSnapshotValue);
638 PacketBeginningMessage::Shared _createPacketBeginningMessage(const ConstPacket packet) const
640 return _mSelfMsgIter.createPacketBeginningMessage(packet);
643 PacketBeginningMessage::Shared
644 _createPacketBeginningMessage(const ConstPacket packet,
645 const std::uint64_t clockSnapshotValue) const
647 return _mSelfMsgIter.createPacketBeginningMessage(packet, clockSnapshotValue);
650 PacketEndMessage::Shared _createPacketEndMessage(const ConstPacket packet) const
652 return _mSelfMsgIter.createPacketEndMessage(packet);
655 PacketEndMessage::Shared _createPacketEndMessage(const ConstPacket packet,
656 const std::uint64_t clockSnapshotValue) const
658 return _mSelfMsgIter.createPacketEndMessage(packet, clockSnapshotValue);
661 DiscardedEventsMessage::Shared _createDiscardedEventsMessage(const ConstStream stream)
663 return _mSelfMsgIter.createDiscardedEventsMessage(stream);
666 DiscardedEventsMessage::Shared
667 _createDiscardedEventsMessage(const ConstStream stream,
668 const std::uint64_t beginningClockSnapshotValue,
669 const std::uint64_t endClockSnapshotValue)
671 return _mSelfMsgIter.createDiscardedEventsMessage(stream, beginningClockSnapshotValue,
672 endClockSnapshotValue);
675 DiscardedPacketsMessage::Shared _createDiscardedPacketsMessage(const ConstStream stream)
677 return _mSelfMsgIter.createDiscardedPacketsMessage(stream);
680 DiscardedPacketsMessage::Shared
681 _createDiscardedPacketsMessage(const ConstStream stream,
682 const std::uint64_t beginningClockSnapshotValue,
683 const std::uint64_t endClockSnapshotValue)
685 return _mSelfMsgIter.createDiscardedPacketsMessage(stream, beginningClockSnapshotValue,
686 endClockSnapshotValue);
689 MessageIteratorInactivityMessage::Shared
690 _createMessageIteratorInactivityMessage(const ConstClockClass clockClass,
691 const std::uint64_t clockSnapshotValue)
693 return _mSelfMsgIter.createMessageIteratorInactivityMessage(clockClass, clockSnapshotValue);
696 UserComponentT& _component() noexcept
698 return _mSelfMsgIter.component().template data<UserComponentT>();
701 SelfComponentOutputPort _port() noexcept
703 return _mSelfMsgIter.port();
706 bool _isInterrupted() const noexcept
708 return _mSelfMsgIter.isInterrupted();
712 UserMessageIteratorT& _userObj() noexcept
714 return static_cast<UserMessageIteratorT&>(*this);
717 void _resetError() noexcept
719 _mExcToThrowType = _ExcToThrowType::NONE;
720 _mSavedLibError.reset();
723 SelfMessageIterator _mSelfMsgIter;
726 * next() may accumulate messages, and then catch an error before
727 * returning. In that case, it saves the error of the current thread
728 * here so that it can return its accumulated messages and throw the
731 * It also saves the type of the exception to throw the next time.
733 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
735 struct LibErrorDeleter final
737 void operator()(const bt_error * const error) const noexcept
739 bt_error_release(error);
743 std::unique_ptr<const bt_error, LibErrorDeleter> _mSavedLibError;
746 bt2c::Logger _mLogger;
751 template <typename UserComponentT, typename CompClsBridgeT, typename LibSpecCompClsPtrT,
752 typename AsCompClsFuncT, typename SetInitMethodFuncT, typename SetFinalizeMethodFuncT,
753 typename SetGetSupportedMipVersionsMethodFuncT, typename SetQueryMethodFuncT>
754 void setCompClsCommonProps(
755 LibSpecCompClsPtrT * const libSpecCompClsPtr, AsCompClsFuncT&& asCompClsFunc,
756 SetInitMethodFuncT&& setInitMethodFunc, SetFinalizeMethodFuncT&& setFinalizeMethodFunc,
757 SetGetSupportedMipVersionsMethodFuncT&& setGetSupportedMipVersionsMethodFunc,
758 SetQueryMethodFuncT&& setQueryMethodFunc)
760 const auto libCompClsPtr = asCompClsFunc(libSpecCompClsPtr);
762 if (UserComponentT::description != nullptr) {
764 bt_component_class_set_description(libCompClsPtr, UserComponentT::description);
766 if (status == BT_COMPONENT_CLASS_SET_DESCRIPTION_STATUS_MEMORY_ERROR) {
767 throw MemoryError {};
771 if (UserComponentT::help != nullptr) {
772 const auto status = bt_component_class_set_help(libCompClsPtr, UserComponentT::help);
774 if (status == BT_COMPONENT_CLASS_SET_HELP_STATUS_MEMORY_ERROR) {
775 throw MemoryError {};
780 const auto status = setInitMethodFunc(libSpecCompClsPtr, CompClsBridgeT::init);
782 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
786 const auto status = setFinalizeMethodFunc(libSpecCompClsPtr, CompClsBridgeT::finalize);
788 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
792 const auto status = setGetSupportedMipVersionsMethodFunc(
793 libSpecCompClsPtr, CompClsBridgeT::getSupportedMipVersions);
795 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
799 const auto status = setQueryMethodFunc(libSpecCompClsPtr, CompClsBridgeT::query);
801 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
805 template <typename MsgIterClsBridgeT>
806 bt_message_iterator_class *createLibMsgIterCls()
808 const auto libMsgIterClsPtr = bt_message_iterator_class_create(MsgIterClsBridgeT::next);
810 if (!libMsgIterClsPtr) {
811 throw MemoryError {};
815 const auto status = bt_message_iterator_class_set_initialize_method(
816 libMsgIterClsPtr, MsgIterClsBridgeT::init);
818 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
822 const auto status = bt_message_iterator_class_set_finalize_method(
823 libMsgIterClsPtr, MsgIterClsBridgeT::finalize);
825 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
828 return libMsgIterClsPtr;
831 template <typename UserComponentT>
832 bt_component_class_source *createSourceCompCls()
835 std::is_base_of<UserSourceComponent<
836 UserComponentT, typename UserComponentT::MessageIterator,
837 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
838 UserComponentT>::value,
839 "`UserComponentT` inherits `UserSourceComponent`");
841 using CompClsBridge = internal::SrcCompClsBridge<UserComponentT>;
842 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
844 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
845 const auto libCompClsPtr =
846 bt_component_class_source_create(UserComponentT::name, libMsgIterClsPtr);
848 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
850 if (!libCompClsPtr) {
851 throw MemoryError {};
854 setCompClsCommonProps<UserComponentT, CompClsBridge>(
855 libCompClsPtr, bt_component_class_source_as_component_class,
856 bt_component_class_source_set_initialize_method,
857 bt_component_class_source_set_finalize_method,
858 bt_component_class_source_set_get_supported_mip_versions_method,
859 bt_component_class_source_set_query_method);
862 const auto status = bt_component_class_source_set_output_port_connected_method(
863 libCompClsPtr, CompClsBridge::outputPortConnected);
865 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
868 return libCompClsPtr;
871 template <typename UserComponentT>
872 bt_component_class_filter *createFilterCompCls()
875 std::is_base_of<UserFilterComponent<
876 UserComponentT, typename UserComponentT::MessageIterator,
877 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
878 UserComponentT>::value,
879 "`UserComponentT` inherits `UserFilterComponent`");
881 using CompClsBridge = internal::FltCompClsBridge<UserComponentT>;
882 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
884 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
885 const auto libCompClsPtr =
886 bt_component_class_filter_create(UserComponentT::name, libMsgIterClsPtr);
888 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
890 if (!libCompClsPtr) {
891 throw MemoryError {};
894 setCompClsCommonProps<UserComponentT, CompClsBridge>(
895 libCompClsPtr, bt_component_class_filter_as_component_class,
896 bt_component_class_filter_set_initialize_method,
897 bt_component_class_filter_set_finalize_method,
898 bt_component_class_filter_set_get_supported_mip_versions_method,
899 bt_component_class_filter_set_query_method);
902 const auto status = bt_component_class_filter_set_input_port_connected_method(
903 libCompClsPtr, CompClsBridge::inputPortConnected);
905 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
909 const auto status = bt_component_class_filter_set_output_port_connected_method(
910 libCompClsPtr, CompClsBridge::outputPortConnected);
912 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
915 return libCompClsPtr;
918 template <typename UserComponentT>
919 bt_component_class_sink *createSinkCompCls()
922 std::is_base_of<UserSinkComponent<UserComponentT, typename UserComponentT::InitData,
923 typename UserComponentT::QueryData>,
924 UserComponentT>::value,
925 "`UserComponentT` inherits `UserSinkComponent`");
927 using CompClsBridge = internal::SinkCompClsBridge<UserComponentT>;
929 const auto libCompClsPtr =
930 bt_component_class_sink_create(UserComponentT::name, CompClsBridge::consume);
932 if (!libCompClsPtr) {
933 throw MemoryError {};
936 setCompClsCommonProps<UserComponentT, CompClsBridge>(
937 libCompClsPtr, bt_component_class_sink_as_component_class,
938 bt_component_class_sink_set_initialize_method, bt_component_class_sink_set_finalize_method,
939 bt_component_class_sink_set_get_supported_mip_versions_method,
940 bt_component_class_sink_set_query_method);
943 const auto status = bt_component_class_sink_set_graph_is_configured_method(
944 libCompClsPtr, CompClsBridge::graphIsConfigured);
946 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
950 const auto status = bt_component_class_sink_set_input_port_connected_method(
951 libCompClsPtr, CompClsBridge::inputPortConnected);
953 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
956 return libCompClsPtr;
959 } /* namespace internal */
960 } /* namespace bt2 */
962 #endif /* BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP */