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 *,
121 const bt_value ** const libResultPtr) noexcept
123 const auto privQueryExec = wrap(libPrivQueryExecPtr);
126 auto result = UserCompClsT::query(wrap(libSelfCompClsPtr), privQueryExec, object,
129 *libResultPtr = result.release().libObjPtr();
130 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
131 } catch (const TryAgain&) {
132 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
133 } catch (const UnknownObject&) {
134 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
135 } catch (const std::bad_alloc&) {
136 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
137 } catch (const Error&) {
138 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
140 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
141 unhandledExcLogTag(), unhandledExcLogStr());
142 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
147 template <typename SpecCompClsBridgeT, typename LibTypesT>
148 struct CompClsBridgeWithInputPorts
150 static bt_component_class_port_connected_method_status
151 inputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
152 bt_self_component_port_input * const libSelfCompPortPtr,
153 const bt_port_output * const libOtherPortPtr) noexcept
156 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
157 .inputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
158 } catch (const std::bad_alloc&) {
159 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
160 } catch (const Error&) {
161 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
163 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
164 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
165 unhandledExcLogTag(), unhandledExcLogStr());
166 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
169 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
173 template <typename SpecCompClsBridgeT, typename LibTypesT>
174 struct CompClsBridgeWithOutputPorts
176 static bt_component_class_port_connected_method_status
177 outputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
178 bt_self_component_port_output * const libSelfCompPortPtr,
179 const bt_port_input * const libOtherPortPtr) noexcept
182 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
183 .outputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
184 } catch (const std::bad_alloc&) {
185 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
186 } catch (const Error&) {
187 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
189 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
190 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
191 unhandledExcLogTag(), unhandledExcLogStr());
192 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
195 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
199 struct SrcCompClsLibTypes final
201 using SelfCompCls = bt_self_component_class_source;
202 using SelfComp = bt_self_component_source;
203 using SelfCompCfg = bt_self_component_source_configuration;
206 template <typename UserCompClsT>
207 class SrcCompClsBridge final :
208 public CompClsBridge<UserCompClsT, SrcCompClsLibTypes>,
209 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsLibTypes>
213 struct FltCompClsLibTypes final
215 using SelfCompCls = bt_self_component_class_filter;
216 using SelfComp = bt_self_component_filter;
217 using SelfCompCfg = bt_self_component_filter_configuration;
220 template <typename UserCompClsT>
221 class FltCompClsBridge final :
222 public CompClsBridge<UserCompClsT, FltCompClsLibTypes>,
223 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>,
224 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>
228 struct SinkCompClsLibTypes final
230 using SelfCompCls = bt_self_component_class_sink;
231 using SelfComp = bt_self_component_sink;
232 using SelfCompCfg = bt_self_component_sink_configuration;
235 template <typename UserCompClsT>
236 class SinkCompClsBridge final :
237 CompClsBridge<UserCompClsT, SinkCompClsLibTypes>,
238 CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsLibTypes>
241 using CompClsBridge<UserCompClsT, SinkCompClsLibTypes>::userCompFromLibSelfCompPtr;
244 static bt_component_class_sink_consume_method_status
245 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
248 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
249 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
251 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
253 } catch (const TryAgain&) {
254 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
255 } catch (const std::bad_alloc&) {
256 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
257 } catch (const Error&) {
258 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
260 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
261 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
262 unhandledExcLogTag(), unhandledExcLogStr());
263 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
267 static bt_component_class_sink_graph_is_configured_method_status
268 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
271 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
272 } catch (const std::bad_alloc&) {
273 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
274 } catch (const Error&) {
275 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
277 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
278 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
279 unhandledExcLogTag(), unhandledExcLogStr());
280 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
285 template <typename UserMsgIterT>
286 class MsgIterClsBridge final
290 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
292 return bt2::wrap(libSelfMsgIterPtr).data<UserMsgIterT>();
295 static bt_message_iterator_class_initialize_method_status
296 init(bt_self_message_iterator * const libSelfMsgIterPtr,
297 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
298 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
300 const auto selfMsgIter = bt2::wrap(libSelfMsgIterPtr);
303 const auto msgIter = new UserMsgIterT {selfMsgIter, bt2::wrap(libSelfMsgIterConfigPtr),
304 bt2::wrap(libSelfCompPortPtr)};
306 selfMsgIter.data(*msgIter);
307 } catch (const std::bad_alloc&) {
308 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
309 } catch (const bt2::Error&) {
310 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
312 BT_LOG_WRITE_CUR_LVL(
314 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
315 unhandledExcLogTag(), unhandledExcLogStr());
316 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
319 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
322 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
324 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
327 static bt_message_iterator_class_next_method_status
328 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
329 const uint64_t capacity, uint64_t * const count) noexcept
332 auto msgArray = bt2::ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
333 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
335 msgIter.next(msgArray);
336 *count = msgArray.release();
338 if (G_LIKELY(*count > 0)) {
339 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
341 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
343 } catch (const bt2::TryAgain&) {
344 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
345 } catch (const std::bad_alloc&) {
346 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
347 } catch (const bt2::Error&) {
348 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
350 BT_LOG_WRITE_CUR_LVL(
352 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
353 unhandledExcLogTag(), unhandledExcLogStr());
354 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
358 static bt_message_iterator_class_can_seek_beginning_method_status
359 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
360 bt_bool * const canSeek) noexcept
363 *canSeek = static_cast<bt_bool>(
364 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
365 } catch (const bt2::TryAgain&) {
366 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
367 } catch (const std::bad_alloc&) {
368 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
369 } catch (const bt2::Error&) {
370 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
372 BT_LOG_WRITE_CUR_LVL(
374 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
375 unhandledExcLogTag(), unhandledExcLogStr());
376 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
379 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
382 static bt_message_iterator_class_seek_beginning_method_status
383 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
386 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
387 } catch (const bt2::TryAgain&) {
388 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
389 } catch (const std::bad_alloc&) {
390 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
391 } catch (const bt2::Error&) {
392 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
394 BT_LOG_WRITE_CUR_LVL(
396 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
397 unhandledExcLogTag(), unhandledExcLogStr());
398 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
401 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
404 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
405 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
406 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
409 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
410 .canSeekNsFromOrigin(nsFromOrigin));
411 } catch (const bt2::TryAgain&) {
412 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
413 } catch (const std::bad_alloc&) {
414 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
415 } catch (const bt2::Error&) {
416 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
418 BT_LOG_WRITE_CUR_LVL(
420 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
421 unhandledExcLogTag(), unhandledExcLogStr());
422 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
425 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
428 static bt_message_iterator_class_seek_ns_from_origin_method_status
429 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
430 const std::int64_t nsFromOrigin) noexcept
433 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
434 } catch (const bt2::TryAgain&) {
435 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
436 } catch (const std::bad_alloc&) {
437 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
438 } catch (const bt2::Error&) {
439 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
441 BT_LOG_WRITE_CUR_LVL(
443 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
444 unhandledExcLogTag(), unhandledExcLogStr());
445 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
448 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
452 } /* namespace internal */
454 template <typename UserMessageIteratorT, typename UserComponentT>
455 class UserMessageIterator;
458 * Base class of any user component.
460 * See the specific `bt2::UserSourceComponent`,
461 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
463 template <typename SelfCompT, typename InitDataT>
466 /* Give a related message iterator access to this logger */
467 template <typename, typename>
468 friend class UserMessageIterator;
471 using InitData = InitDataT;
474 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
475 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
480 bt2c::CStringView _name() const noexcept
482 return _mSelfComp.name();
485 LoggingLevel _loggingLevel() const noexcept
487 return _mSelfComp.loggingLevel();
490 std::uint64_t _graphMipVersion() const noexcept
492 return _mSelfComp.graphMipVersion();
495 SelfCompT _selfComp() noexcept
500 bt2c::Logger _mLogger;
503 SelfCompT _mSelfComp;
507 * Base class of a user source component `UserComponentT` (CRTP).
509 * UserComponentT::UserComponentT() must accept, in this order:
511 * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward
512 * to bt2::UserSourceComponent::UserSourceComponent().
514 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
516 * 3. An `InitDataT *` parameter (the initialization method data).
518 * `UserMessageIteratorT`, the message iterator class to use, must inherit
519 * `UserMessageIterator`.
521 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void>
522 class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT>
524 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
525 UserMessageIteratorT>::value,
526 "`UserMessageIteratorT` inherits `UserMessageIterator`");
529 using MessageIterator = UserMessageIteratorT;
532 using _OutputPorts = SelfSourceComponent::OutputPorts;
534 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
535 UserComponent<SelfSourceComponent, InitDataT> {selfComp, logTag}
540 static Value::Shared query(const SelfComponentClass selfCompCls,
541 const PrivateQueryExecutor privQueryExec,
542 const bt2c::CStringView obj, const ConstValue params)
544 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
547 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
548 const ConstValue params, const LoggingLevel loggingLevel,
549 const UnsignedIntegerRangeSet ranges)
551 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
554 void outputPortConnected(const SelfComponentOutputPort outputPort,
555 const ConstInputPort inputPort)
557 static_cast<UserComponentT&>(*this).outputPortConnected(outputPort, inputPort);
562 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
565 throw UnknownObject {};
569 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
570 const UnsignedIntegerRangeSet ranges)
572 ranges.addRange(0, 0);
576 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
580 template <typename DataT>
581 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
583 return this->_selfComp().addOutputPort(name, data);
586 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
588 return this->_selfComp().addOutputPort(name);
591 _OutputPorts _outputPorts() noexcept
593 return this->_selfComp().outputPorts();
598 * Base class of a user filter component `UserComponentT` (CRTP).
600 * UserComponentT::UserComponentT() must accept, in this order:
602 * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward
603 * to bt2::UserFilterComponent::UserFilterComponent().
605 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
607 * 3. An `InitDataT *` parameter (the initialization method data).
609 * `UserMessageIteratorT`, the message iterator class to use, must inherit
610 * `UserMessageIterator`.
612 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void>
613 class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT>
615 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
616 UserMessageIteratorT>::value,
617 "`UserMessageIteratorT` inherits `UserMessageIterator`");
620 using MessageIterator = UserMessageIteratorT;
623 using _InputPorts = SelfFilterComponent::InputPorts;
624 using _OutputPorts = SelfFilterComponent::OutputPorts;
626 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
627 UserComponent<SelfFilterComponent, InitDataT> {selfComp, logTag}
632 static Value::Shared query(const SelfComponentClass selfCompCls,
633 const PrivateQueryExecutor privQueryExec,
634 const bt2c::CStringView obj, const ConstValue params)
636 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
639 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
640 const ConstValue params, const LoggingLevel loggingLevel,
641 const UnsignedIntegerRangeSet ranges)
643 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
646 void inputPortConnected(const SelfComponentInputPort inputPort,
647 const ConstOutputPort outputPort)
649 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
652 void outputPortConnected(const SelfComponentOutputPort outputPort,
653 const ConstInputPort inputPort)
655 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
660 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
663 throw UnknownObject {};
667 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
668 const UnsignedIntegerRangeSet ranges)
670 ranges.addRange(0, 0);
674 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
679 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
683 template <typename DataT>
684 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
686 return this->_selfComp().addInputPort(name, data);
689 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
691 return this->_selfComp().addInputPort(name);
694 _InputPorts _inputPorts() noexcept
696 return this->_selfComp().inputPorts();
699 template <typename DataT>
700 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
702 return this->_selfComp().addOutputPort(name, data);
705 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
707 return this->_selfComp().addOutputPort(name);
710 _OutputPorts _outputPorts() noexcept
712 return this->_selfComp().outputPorts();
717 * Base class of a user sink component `UserComponentT` (CRTP).
719 * UserComponentT::UserComponentT() must accept, in this order:
721 * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward
722 * to bt2::UserSinkComponent::UserSinkComponent().
724 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
726 * 3. An `InitDataT *` parameter (the initialization method data).
728 * `UserComponentT` must implement:
732 * This method returns `true` if the sink component still needs to
733 * consume, or `false` if it's finished.
735 template <typename UserComponentT, typename InitDataT = void>
736 class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT>
739 using _InputPorts = SelfSinkComponent::InputPorts;
741 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
742 UserComponent<SelfSinkComponent, InitDataT> {selfComp, logTag}
747 static Value::Shared query(const SelfComponentClass selfCompCls,
748 const PrivateQueryExecutor privQueryExec,
749 const bt2c::CStringView obj, const ConstValue params)
751 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
754 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
755 const ConstValue params, const LoggingLevel loggingLevel,
756 const UnsignedIntegerRangeSet ranges)
758 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
761 void graphIsConfigured()
763 static_cast<UserComponentT&>(*this)._graphIsConfigured();
766 void inputPortConnected(const SelfComponentInputPort inputPort,
767 const ConstOutputPort outputPort)
769 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
774 return static_cast<UserComponentT&>(*this)._consume();
779 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
782 throw UnknownObject {};
786 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
787 const UnsignedIntegerRangeSet ranges)
789 ranges.addRange(0, 0);
793 void _graphIsConfigured()
798 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
802 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
804 return this->_selfComp().createMessageIterator(port);
807 template <typename DataT>
808 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
810 return this->_selfComp().addInputPort(name, data);
813 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
815 return this->_selfComp().addInputPort(name);
818 _InputPorts _inputPorts() noexcept
820 return this->_selfComp().inputPorts();
825 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
826 * of which the parent user component class is `UserComponentT`.
828 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
829 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
830 * bt2::UserMessageIterator::UserMessageIterator().
832 * The public next() method below (called by the bridge) implements the
833 * very common pattern of appending messages into the output array, and,
836 * If it catches a `bt2::TryAgain` exception:
837 * If the message array isn't empty, transform this into a success
842 * If it catches an error:
843 * If the message array isn't empty, transform this into a success
844 * (don't throw), but save the error of the current thread and the
845 * type of error to throw the next time the user calls next().
849 * `UserMessageIteratorT` must implement:
851 * void _next(bt2::ConstMessageArray& messages);
853 * This method fills `messages` with at most `messages.capacity()`
854 * messages and may throw `bt2::TryAgain` or a valid error whenever.
855 * Leaving an empty `messages` means the end of iteration.
857 template <typename UserMessageIteratorT, typename UserComponentT>
858 class UserMessageIterator
861 /* Type of `_mExcToThrowType` */
862 enum class _ExcToThrowType
870 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
871 const std::string& logTagSuffix) :
872 _mSelfMsgIter {selfMsgIter},
873 _mLogger {selfMsgIter,
874 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
879 ~UserMessageIterator()
884 void next(bt2::ConstMessageArray& messages)
886 /* Any saved error? Now is the time to throw */
887 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
888 /* Move `_mSavedLibError`, if any, as current thread error */
889 if (_mSavedLibError) {
890 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError);
893 /* Throw the corresponding exception */
894 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
897 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
898 throw bt2::MemoryError {};
903 * When catching some exception below, if our message array
904 * isn't empty, then return immediately before throwing to
905 * provide those messages to downstream.
907 * When catching an error, also save the current thread error,
908 * if any, so that we can restore it later (see the beginning of
911 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
914 this->_userObj()._next(messages);
916 /* We're done: everything below is exception handling */
918 } catch (const bt2::TryAgain&) {
919 if (messages.isEmpty()) {
922 } catch (const std::bad_alloc&) {
923 if (messages.isEmpty()) {
927 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
928 } catch (const bt2::Error&) {
929 if (messages.isEmpty()) {
933 _mExcToThrowType = _ExcToThrowType::ERROR;
936 if (_mExcToThrowType != _ExcToThrowType::NONE) {
938 "An error occurred, but there are {} messages to return: delaying the error reporting.",
940 BT_ASSERT(!_mSavedLibError);
941 _mSavedLibError = bt_current_thread_take_error();
945 bool canSeekBeginning()
948 return this->_userObj()._canSeekBeginning();
954 return this->_userObj()._seekBeginning();
957 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
960 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
963 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
966 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
971 bool _canSeekBeginning() noexcept
977 void _seekBeginning() noexcept
982 bool _canSeekNsFromOrigin(std::int64_t) noexcept
988 void _seekNsFromOrigin(std::int64_t) noexcept
992 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
994 return _mSelfMsgIter.createMessageIterator(port);
997 UserComponentT& _component() noexcept
999 return _mSelfMsgIter.component().template data<UserComponentT>();
1002 SelfComponentOutputPort _port() noexcept
1004 return _mSelfMsgIter.port();
1007 bool _isInterrupted() const noexcept
1009 return _mSelfMsgIter.isInterrupted();
1013 UserMessageIteratorT& _userObj() noexcept
1015 return static_cast<UserMessageIteratorT&>(*this);
1018 void _resetError() noexcept
1020 _mExcToThrowType = _ExcToThrowType::NONE;
1022 if (_mSavedLibError) {
1023 bt_error_release(_mSavedLibError);
1027 SelfMessageIterator _mSelfMsgIter;
1030 * next() may accumulate messages, and then catch an error before
1031 * returning. In that case, it saves the error of the current thread
1032 * here so that it can return its accumulated messages and throw the
1035 * It also saves the type of the exception to throw the next time.
1037 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
1038 const bt_error *_mSavedLibError = nullptr;
1041 bt2c::Logger _mLogger;
1044 } /* namespace bt2 */
1046 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1047 _userComponentClass) \
1048 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1049 _pluginId, _componentClassId, _name, \
1050 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1051 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1052 _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \
1053 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1054 _pluginId, _componentClassId, \
1055 bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \
1056 BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1057 _pluginId, _componentClassId, \
1058 bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1059 BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1060 _pluginId, _componentClassId, \
1061 bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \
1062 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1063 _pluginId, _componentClassId, \
1064 bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \
1065 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1066 _pluginId, _componentClassId, \
1067 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1068 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1069 _pluginId, _componentClassId, \
1070 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1071 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1072 _pluginId, _componentClassId, \
1073 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1074 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1075 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1076 _pluginId, _componentClassId, \
1077 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1078 bt2::internal::MsgIterClsBridge< \
1079 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1081 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1082 _userComponentClass) \
1083 BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1084 _pluginId, _componentClassId, _name, \
1085 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1086 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1087 _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \
1088 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1089 _pluginId, _componentClassId, \
1090 bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \
1091 BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1092 _pluginId, _componentClassId, \
1093 bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1094 BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1095 _pluginId, _componentClassId, \
1096 bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \
1097 BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1098 _pluginId, _componentClassId, \
1099 bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \
1100 BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1101 _pluginId, _componentClassId, \
1102 bt2::internal::FltCompClsBridge<_userComponentClass>::query); \
1103 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1104 _pluginId, _componentClassId, \
1105 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1106 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1107 _pluginId, _componentClassId, \
1108 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1109 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1110 _pluginId, _componentClassId, \
1111 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1112 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1113 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1114 _pluginId, _componentClassId, \
1115 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1116 bt2::internal::MsgIterClsBridge< \
1117 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1119 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1120 _userComponentClass) \
1121 BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \
1122 _pluginId, _componentClassId, _name, \
1123 bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \
1124 BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1125 _pluginId, _componentClassId, \
1126 bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \
1127 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1128 _pluginId, _componentClassId, \
1129 bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \
1130 BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1131 _pluginId, _componentClassId, \
1132 bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1133 BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1134 _pluginId, _componentClassId, \
1135 bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \
1136 BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \
1137 _pluginId, _componentClassId, \
1138 bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \
1139 BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1140 _pluginId, _componentClassId, \
1141 bt2::internal::SinkCompClsBridge<_userComponentClass>::query);
1143 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass) \
1144 BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1146 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass) \
1147 BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1149 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \
1150 BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1152 #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */