2 * Copyright (c) 2023 Simon Marchi <simon.marchi@efficios.com>
3 * Copyright (c) 2023 Philippe Proulx <pproulx@efficios.com>
5 * SPDX-License-Identifier: MIT
8 #ifndef BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP
9 #define BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP
15 #include <babeltrace2/babeltrace.h>
17 #include "cpp-common/bt2c/c-string-view.hpp"
18 #include "cpp-common/bt2c/logging.hpp"
19 #include "cpp-common/vendor/fmt/core.h"
27 constexpr bt2c::CStringView unhandledExcLogStr() noexcept
29 return "Unhandled exception.";
32 constexpr bt2c::CStringView unhandledExcLogTag() noexcept
34 return "PLUGIN-DEV-HPP";
38 * Base class of any component class bridge.
40 * `UserCompClsT` is the actual C++ user component class and `LibTypesT`
41 * is a structure offering the following specific library types:
44 * Self component class.
50 * Self component configuration.
52 template <typename UserCompClsT, typename LibTypesT>
56 using _LibSelfCompPtr = typename LibTypesT::SelfComp *;
59 static UserCompClsT& userCompFromLibSelfCompPtr(const _LibSelfCompPtr libSelfCompPtr) noexcept
61 return wrap(libSelfCompPtr).template data<UserCompClsT>();
64 static bt_component_class_initialize_method_status init(const _LibSelfCompPtr libSelfCompPtr,
65 typename LibTypesT::SelfCompCfg *,
66 const bt_value * const libParamsPtr,
67 void * const initData) noexcept
69 const auto selfComp = wrap(libSelfCompPtr);
73 new UserCompClsT {selfComp, wrap(libParamsPtr).asMap(),
74 static_cast<typename UserCompClsT::InitData *>(initData)};
77 } catch (const std::bad_alloc&) {
78 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
79 } catch (const Error&) {
80 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
82 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(selfComp.loggingLevel()),
83 unhandledExcLogTag(), unhandledExcLogStr());
84 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
87 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
90 static void finalize(const _LibSelfCompPtr libSelfCompPtr) noexcept
92 delete &userCompFromLibSelfCompPtr(libSelfCompPtr);
95 static bt_component_class_get_supported_mip_versions_method_status
96 getSupportedMipVersions(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
97 const bt_value * const libParamsPtr, void *,
98 const bt_logging_level logLevel,
99 bt_integer_range_set_unsigned * const libSupportedVersionsPtr) noexcept
102 UserCompClsT::getSupportedMipVersions(wrap(libSelfCompClsPtr), wrap(libParamsPtr),
103 static_cast<LoggingLevel>(logLevel),
104 wrap(libSupportedVersionsPtr));
105 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_OK;
106 } catch (const std::bad_alloc&) {
107 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_MEMORY_ERROR;
108 } catch (const Error&) {
109 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
111 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(logLevel), unhandledExcLogTag(),
112 unhandledExcLogStr());
113 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
117 static bt_component_class_query_method_status
118 query(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
119 bt_private_query_executor * const libPrivQueryExecPtr, const char * const object,
120 const bt_value * const libParamsPtr, void * const data,
121 const bt_value ** const libResultPtr) noexcept
123 const auto privQueryExec = wrap(libPrivQueryExecPtr);
126 auto result = UserCompClsT::query(
127 wrap(libSelfCompClsPtr), privQueryExec, object, wrap(libParamsPtr),
128 static_cast<typename UserCompClsT::QueryData *>(data));
130 *libResultPtr = result.release().libObjPtr();
131 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
132 } catch (const TryAgain&) {
133 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
134 } catch (const UnknownObject&) {
135 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
136 } catch (const std::bad_alloc&) {
137 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
138 } catch (const Error&) {
139 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
141 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
142 unhandledExcLogTag(), unhandledExcLogStr());
143 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
148 template <typename SpecCompClsBridgeT, typename LibTypesT>
149 struct CompClsBridgeWithInputPorts
151 static bt_component_class_port_connected_method_status
152 inputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
153 bt_self_component_port_input * const libSelfCompPortPtr,
154 const bt_port_output * const libOtherPortPtr) noexcept
157 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
158 .inputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
159 } catch (const std::bad_alloc&) {
160 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
161 } catch (const Error&) {
162 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
164 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
165 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
166 unhandledExcLogTag(), unhandledExcLogStr());
167 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
170 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
174 template <typename SpecCompClsBridgeT, typename LibTypesT>
175 struct CompClsBridgeWithOutputPorts
177 static bt_component_class_port_connected_method_status
178 outputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
179 bt_self_component_port_output * const libSelfCompPortPtr,
180 const bt_port_input * const libOtherPortPtr) noexcept
183 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
184 .outputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
185 } catch (const std::bad_alloc&) {
186 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
187 } catch (const Error&) {
188 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
190 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
191 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
192 unhandledExcLogTag(), unhandledExcLogStr());
193 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
196 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
200 struct SrcCompClsLibTypes final
202 using SelfCompCls = bt_self_component_class_source;
203 using SelfComp = bt_self_component_source;
204 using SelfCompCfg = bt_self_component_source_configuration;
207 template <typename UserCompClsT>
208 class SrcCompClsBridge final :
209 public CompClsBridge<UserCompClsT, SrcCompClsLibTypes>,
210 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsLibTypes>
214 struct FltCompClsLibTypes final
216 using SelfCompCls = bt_self_component_class_filter;
217 using SelfComp = bt_self_component_filter;
218 using SelfCompCfg = bt_self_component_filter_configuration;
221 template <typename UserCompClsT>
222 class FltCompClsBridge final :
223 public CompClsBridge<UserCompClsT, FltCompClsLibTypes>,
224 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>,
225 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>
229 struct SinkCompClsLibTypes final
231 using SelfCompCls = bt_self_component_class_sink;
232 using SelfComp = bt_self_component_sink;
233 using SelfCompCfg = bt_self_component_sink_configuration;
236 template <typename UserCompClsT>
237 class SinkCompClsBridge final :
238 public CompClsBridge<UserCompClsT, SinkCompClsLibTypes>,
239 public CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsLibTypes>
242 using CompClsBridge<UserCompClsT, SinkCompClsLibTypes>::userCompFromLibSelfCompPtr;
245 static bt_component_class_sink_consume_method_status
246 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
249 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
250 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
252 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
254 } catch (const TryAgain&) {
255 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
256 } catch (const std::bad_alloc&) {
257 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
258 } catch (const Error&) {
259 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
261 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
262 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
263 unhandledExcLogTag(), unhandledExcLogStr());
264 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
268 static bt_component_class_sink_graph_is_configured_method_status
269 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
272 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
273 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK;
274 } catch (const std::bad_alloc&) {
275 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
276 } catch (const Error&) {
277 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
279 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
280 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
281 unhandledExcLogTag(), unhandledExcLogStr());
282 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
287 template <typename UserMsgIterT>
288 class MsgIterClsBridge final
292 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
294 return bt2::wrap(libSelfMsgIterPtr).data<UserMsgIterT>();
297 static bt_message_iterator_class_initialize_method_status
298 init(bt_self_message_iterator * const libSelfMsgIterPtr,
299 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
300 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
302 const auto selfMsgIter = bt2::wrap(libSelfMsgIterPtr);
305 const auto msgIter = new UserMsgIterT {selfMsgIter, bt2::wrap(libSelfMsgIterConfigPtr),
306 bt2::wrap(libSelfCompPortPtr)};
308 selfMsgIter.data(*msgIter);
309 } catch (const std::bad_alloc&) {
310 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
311 } catch (const bt2::Error&) {
312 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
314 BT_LOG_WRITE_CUR_LVL(
316 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
317 unhandledExcLogTag(), unhandledExcLogStr());
318 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
321 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
324 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
326 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
329 static bt_message_iterator_class_next_method_status
330 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
331 const uint64_t capacity, uint64_t * const count) noexcept
334 auto msgArray = bt2::ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
335 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
337 msgIter.next(msgArray);
338 *count = msgArray.release();
340 if (G_LIKELY(*count > 0)) {
341 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
343 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
345 } catch (const bt2::TryAgain&) {
346 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
347 } catch (const std::bad_alloc&) {
348 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
349 } catch (const bt2::Error&) {
350 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
352 BT_LOG_WRITE_CUR_LVL(
354 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
355 unhandledExcLogTag(), unhandledExcLogStr());
356 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
360 static bt_message_iterator_class_can_seek_beginning_method_status
361 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
362 bt_bool * const canSeek) noexcept
365 *canSeek = static_cast<bt_bool>(
366 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
367 } catch (const bt2::TryAgain&) {
368 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
369 } catch (const std::bad_alloc&) {
370 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
371 } catch (const bt2::Error&) {
372 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
374 BT_LOG_WRITE_CUR_LVL(
376 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
377 unhandledExcLogTag(), unhandledExcLogStr());
378 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
381 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
384 static bt_message_iterator_class_seek_beginning_method_status
385 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
388 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
389 } catch (const bt2::TryAgain&) {
390 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
391 } catch (const std::bad_alloc&) {
392 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
393 } catch (const bt2::Error&) {
394 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
396 BT_LOG_WRITE_CUR_LVL(
398 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
399 unhandledExcLogTag(), unhandledExcLogStr());
400 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
403 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
406 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
407 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
408 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
411 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
412 .canSeekNsFromOrigin(nsFromOrigin));
413 } catch (const bt2::TryAgain&) {
414 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
415 } catch (const std::bad_alloc&) {
416 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
417 } catch (const bt2::Error&) {
418 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
420 BT_LOG_WRITE_CUR_LVL(
422 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
423 unhandledExcLogTag(), unhandledExcLogStr());
424 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
427 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
430 static bt_message_iterator_class_seek_ns_from_origin_method_status
431 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
432 const std::int64_t nsFromOrigin) noexcept
435 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
436 } catch (const bt2::TryAgain&) {
437 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
438 } catch (const std::bad_alloc&) {
439 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
440 } catch (const bt2::Error&) {
441 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
443 BT_LOG_WRITE_CUR_LVL(
445 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
446 unhandledExcLogTag(), unhandledExcLogStr());
447 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
450 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
454 } /* namespace internal */
456 template <typename UserMessageIteratorT, typename UserComponentT>
457 class UserMessageIterator;
460 * Base class of any user component.
462 * See the specific `bt2::UserSourceComponent`,
463 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
465 template <typename SelfCompT, typename InitDataT, typename QueryDataT>
468 /* Give a related message iterator access to this logger */
469 template <typename, typename>
470 friend class UserMessageIterator;
473 using InitData = InitDataT;
474 using QueryData = QueryDataT;
477 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
478 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
483 bt2c::CStringView _name() const noexcept
485 return _mSelfComp.name();
488 LoggingLevel _loggingLevel() const noexcept
490 return _mSelfComp.loggingLevel();
493 std::uint64_t _graphMipVersion() const noexcept
495 return _mSelfComp.graphMipVersion();
498 SelfCompT _selfComp() noexcept
503 bt2c::Logger _mLogger;
506 SelfCompT _mSelfComp;
510 * Base class of a user source component `UserComponentT` (CRTP).
512 * UserComponentT::UserComponentT() must accept, in this order:
514 * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward
515 * to bt2::UserSourceComponent::UserSourceComponent().
517 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
519 * 3. An `InitDataT *` parameter (the initialization method data).
521 * `UserMessageIteratorT`, the message iterator class to use, must inherit
522 * `UserMessageIterator`.
524 * UserComponentT::_query() receives a query method data pointer of type
525 * `QueryDataT *` as its last parameter.
527 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
528 typename QueryDataT = void>
529 class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT, QueryDataT>
531 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
532 UserMessageIteratorT>::value,
533 "`UserMessageIteratorT` inherits `UserMessageIterator`");
536 using MessageIterator = UserMessageIteratorT;
539 using _OutputPorts = SelfSourceComponent::OutputPorts;
541 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
542 UserComponent<SelfSourceComponent, InitDataT, QueryDataT> {selfComp, logTag}
547 static Value::Shared query(const SelfComponentClass selfCompCls,
548 const PrivateQueryExecutor privQueryExec,
549 const bt2c::CStringView obj, const ConstValue params,
550 QueryDataT * const data)
552 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
555 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
556 const ConstValue params, const LoggingLevel loggingLevel,
557 const UnsignedIntegerRangeSet ranges)
559 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
562 void outputPortConnected(const SelfComponentOutputPort outputPort,
563 const ConstInputPort inputPort)
565 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
570 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
571 ConstValue, QueryDataT *)
573 throw UnknownObject {};
577 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
578 const UnsignedIntegerRangeSet ranges)
580 ranges.addRange(0, 0);
584 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
588 template <typename DataT>
589 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
591 return this->_selfComp().addOutputPort(name, data);
594 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
596 return this->_selfComp().addOutputPort(name);
599 _OutputPorts _outputPorts() noexcept
601 return this->_selfComp().outputPorts();
606 * Base class of a user filter component `UserComponentT` (CRTP).
608 * UserComponentT::UserComponentT() must accept, in this order:
610 * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward
611 * to bt2::UserFilterComponent::UserFilterComponent().
613 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
615 * 3. An `InitDataT *` parameter (the initialization method data).
617 * `UserMessageIteratorT`, the message iterator class to use, must inherit
618 * `UserMessageIterator`.
620 * UserComponentT::_query() receives a query method data pointer of type
621 * `QueryDataT *` as its last parameter.
623 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
624 typename QueryDataT = void>
625 class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT, QueryDataT>
627 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
628 UserMessageIteratorT>::value,
629 "`UserMessageIteratorT` inherits `UserMessageIterator`");
632 using MessageIterator = UserMessageIteratorT;
635 using _InputPorts = SelfFilterComponent::InputPorts;
636 using _OutputPorts = SelfFilterComponent::OutputPorts;
638 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
639 UserComponent<SelfFilterComponent, InitDataT, QueryDataT> {selfComp, logTag}
644 static Value::Shared query(const SelfComponentClass selfCompCls,
645 const PrivateQueryExecutor privQueryExec,
646 const bt2c::CStringView obj, const ConstValue params,
647 QueryDataT * const data)
649 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
652 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
653 const ConstValue params, const LoggingLevel loggingLevel,
654 const UnsignedIntegerRangeSet ranges)
656 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
659 void inputPortConnected(const SelfComponentInputPort inputPort,
660 const ConstOutputPort outputPort)
662 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
665 void outputPortConnected(const SelfComponentOutputPort outputPort,
666 const ConstInputPort inputPort)
668 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
673 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
674 ConstValue, QueryDataT *)
676 throw UnknownObject {};
680 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
681 const UnsignedIntegerRangeSet ranges)
683 ranges.addRange(0, 0);
687 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
692 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
696 template <typename DataT>
697 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
699 return this->_selfComp().addInputPort(name, data);
702 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
704 return this->_selfComp().addInputPort(name);
707 _InputPorts _inputPorts() noexcept
709 return this->_selfComp().inputPorts();
712 template <typename DataT>
713 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
715 return this->_selfComp().addOutputPort(name, data);
718 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
720 return this->_selfComp().addOutputPort(name);
723 _OutputPorts _outputPorts() noexcept
725 return this->_selfComp().outputPorts();
730 * Base class of a user sink component `UserComponentT` (CRTP).
732 * UserComponentT::UserComponentT() must accept, in this order:
734 * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward
735 * to bt2::UserSinkComponent::UserSinkComponent().
737 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
739 * 3. An `InitDataT *` parameter (the initialization method data).
741 * `UserComponentT` must implement:
745 * This method returns `true` if the sink component still needs to
746 * consume, or `false` if it's finished.
748 * UserComponentT::_query() receives a query method data pointer of type
749 * `QueryDataT *` as its last parameter.
752 template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void>
753 class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT>
756 using _InputPorts = SelfSinkComponent::InputPorts;
758 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
759 UserComponent<SelfSinkComponent, InitDataT, QueryDataT> {selfComp, logTag}
764 static Value::Shared query(const SelfComponentClass selfCompCls,
765 const PrivateQueryExecutor privQueryExec,
766 const bt2c::CStringView obj, const ConstValue params,
767 QueryDataT * const data)
769 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
772 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
773 const ConstValue params, const LoggingLevel loggingLevel,
774 const UnsignedIntegerRangeSet ranges)
776 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
779 void graphIsConfigured()
781 static_cast<UserComponentT&>(*this)._graphIsConfigured();
784 void inputPortConnected(const SelfComponentInputPort inputPort,
785 const ConstOutputPort outputPort)
787 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
792 return static_cast<UserComponentT&>(*this)._consume();
797 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
798 ConstValue, QueryDataT *)
800 throw UnknownObject {};
804 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
805 const UnsignedIntegerRangeSet ranges)
807 ranges.addRange(0, 0);
811 void _graphIsConfigured()
816 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
820 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
822 return this->_selfComp().createMessageIterator(port);
825 template <typename DataT>
826 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
828 return this->_selfComp().addInputPort(name, data);
831 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
833 return this->_selfComp().addInputPort(name);
836 _InputPorts _inputPorts() noexcept
838 return this->_selfComp().inputPorts();
843 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
844 * of which the parent user component class is `UserComponentT`.
846 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
847 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
848 * bt2::UserMessageIterator::UserMessageIterator().
850 * The public next() method below (called by the bridge) implements the
851 * very common pattern of appending messages into the output array, and,
854 * If it catches a `bt2::TryAgain` exception:
855 * If the message array isn't empty, transform this into a success
860 * If it catches an error:
861 * If the message array isn't empty, transform this into a success
862 * (don't throw), but save the error of the current thread and the
863 * type of error to throw the next time the user calls next().
867 * `UserMessageIteratorT` must implement:
869 * void _next(bt2::ConstMessageArray& messages);
871 * This method fills `messages` with at most `messages.capacity()`
872 * messages and may throw `bt2::TryAgain` or a valid error whenever.
873 * Leaving an empty `messages` means the end of iteration.
875 template <typename UserMessageIteratorT, typename UserComponentT>
876 class UserMessageIterator
879 /* Type of `_mExcToThrowType` */
880 enum class _ExcToThrowType
888 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
889 const std::string& logTagSuffix) :
890 _mSelfMsgIter {selfMsgIter},
891 _mLogger {selfMsgIter,
892 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
897 ~UserMessageIterator()
902 void next(bt2::ConstMessageArray& messages)
904 /* Any saved error? Now is the time to throw */
905 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
906 /* Move `_mSavedLibError`, if any, as current thread error */
907 if (_mSavedLibError) {
908 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError);
911 /* Throw the corresponding exception */
912 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
915 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
916 throw bt2::MemoryError {};
921 * When catching some exception below, if our message array
922 * isn't empty, then return immediately before throwing to
923 * provide those messages to downstream.
925 * When catching an error, also save the current thread error,
926 * if any, so that we can restore it later (see the beginning of
929 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
932 this->_userObj()._next(messages);
934 /* We're done: everything below is exception handling */
936 } catch (const bt2::TryAgain&) {
937 if (messages.isEmpty()) {
940 } catch (const std::bad_alloc&) {
941 if (messages.isEmpty()) {
945 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
946 } catch (const bt2::Error&) {
947 if (messages.isEmpty()) {
951 _mExcToThrowType = _ExcToThrowType::ERROR;
954 if (_mExcToThrowType != _ExcToThrowType::NONE) {
956 "An error occurred, but there are {} messages to return: delaying the error reporting.",
958 BT_ASSERT(!_mSavedLibError);
959 _mSavedLibError = bt_current_thread_take_error();
963 bool canSeekBeginning()
966 return this->_userObj()._canSeekBeginning();
972 return this->_userObj()._seekBeginning();
975 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
978 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
981 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
984 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
989 bool _canSeekBeginning() noexcept
995 void _seekBeginning() noexcept
1000 bool _canSeekNsFromOrigin(std::int64_t) noexcept
1006 void _seekNsFromOrigin(std::int64_t) noexcept
1010 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
1012 return _mSelfMsgIter.createMessageIterator(port);
1015 UserComponentT& _component() noexcept
1017 return _mSelfMsgIter.component().template data<UserComponentT>();
1020 SelfComponentOutputPort _port() noexcept
1022 return _mSelfMsgIter.port();
1025 bool _isInterrupted() const noexcept
1027 return _mSelfMsgIter.isInterrupted();
1031 UserMessageIteratorT& _userObj() noexcept
1033 return static_cast<UserMessageIteratorT&>(*this);
1036 void _resetError() noexcept
1038 _mExcToThrowType = _ExcToThrowType::NONE;
1040 if (_mSavedLibError) {
1041 bt_error_release(_mSavedLibError);
1045 SelfMessageIterator _mSelfMsgIter;
1048 * next() may accumulate messages, and then catch an error before
1049 * returning. In that case, it saves the error of the current thread
1050 * here so that it can return its accumulated messages and throw the
1053 * It also saves the type of the exception to throw the next time.
1055 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
1056 const bt_error *_mSavedLibError = nullptr;
1059 bt2c::Logger _mLogger;
1062 } /* namespace bt2 */
1064 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1065 _userComponentClass) \
1066 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1067 _pluginId, _componentClassId, _name, \
1068 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1069 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1070 _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \
1071 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1072 _pluginId, _componentClassId, \
1073 bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \
1074 BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1075 _pluginId, _componentClassId, \
1076 bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1077 BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1078 _pluginId, _componentClassId, \
1079 bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \
1080 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1081 _pluginId, _componentClassId, \
1082 bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \
1083 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1084 _pluginId, _componentClassId, \
1085 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1086 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1087 _pluginId, _componentClassId, \
1088 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1089 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1090 _pluginId, _componentClassId, \
1091 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1092 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1093 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1094 _pluginId, _componentClassId, \
1095 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1096 bt2::internal::MsgIterClsBridge< \
1097 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1099 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1100 _userComponentClass) \
1101 BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1102 _pluginId, _componentClassId, _name, \
1103 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1104 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1105 _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \
1106 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1107 _pluginId, _componentClassId, \
1108 bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \
1109 BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1110 _pluginId, _componentClassId, \
1111 bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1112 BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1113 _pluginId, _componentClassId, \
1114 bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \
1115 BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1116 _pluginId, _componentClassId, \
1117 bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \
1118 BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1119 _pluginId, _componentClassId, \
1120 bt2::internal::FltCompClsBridge<_userComponentClass>::query); \
1121 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1122 _pluginId, _componentClassId, \
1123 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1124 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1125 _pluginId, _componentClassId, \
1126 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1127 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1128 _pluginId, _componentClassId, \
1129 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1130 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1131 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1132 _pluginId, _componentClassId, \
1133 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1134 bt2::internal::MsgIterClsBridge< \
1135 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1137 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1138 _userComponentClass) \
1139 BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \
1140 _pluginId, _componentClassId, _name, \
1141 bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \
1142 BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1143 _pluginId, _componentClassId, \
1144 bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \
1145 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1146 _pluginId, _componentClassId, \
1147 bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \
1148 BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1149 _pluginId, _componentClassId, \
1150 bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1151 BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1152 _pluginId, _componentClassId, \
1153 bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \
1154 BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \
1155 _pluginId, _componentClassId, \
1156 bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \
1157 BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1158 _pluginId, _componentClassId, \
1159 bt2::internal::SinkCompClsBridge<_userComponentClass>::query);
1161 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass) \
1162 BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1164 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass) \
1165 BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1167 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \
1168 BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1170 #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */