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,
69 const auto selfComp = wrap(libSelfCompPtr);
72 const auto comp = new UserCompClsT {selfComp, wrap(libParamsPtr).asMap()};
75 } catch (const std::bad_alloc&) {
76 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
77 } catch (const Error&) {
78 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
80 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(selfComp.loggingLevel()),
81 unhandledExcLogTag(), unhandledExcLogStr());
82 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
85 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
88 static void finalize(const _LibSelfCompPtr libSelfCompPtr) noexcept
90 delete &userCompFromLibSelfCompPtr(libSelfCompPtr);
93 static bt_component_class_get_supported_mip_versions_method_status
94 getSupportedMipVersions(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
95 const bt_value * const libParamsPtr, void *,
96 const bt_logging_level logLevel,
97 bt_integer_range_set_unsigned * const libSupportedVersionsPtr) noexcept
100 UserCompClsT::getSupportedMipVersions(wrap(libSelfCompClsPtr), wrap(libParamsPtr),
101 static_cast<LoggingLevel>(logLevel),
102 wrap(libSupportedVersionsPtr));
103 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_OK;
104 } catch (const std::bad_alloc&) {
105 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_MEMORY_ERROR;
106 } catch (const Error&) {
107 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
109 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(logLevel), unhandledExcLogTag(),
110 unhandledExcLogStr());
111 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
115 static bt_component_class_query_method_status
116 query(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
117 bt_private_query_executor * const libPrivQueryExecPtr, const char * const object,
118 const bt_value * const libParamsPtr, void *,
119 const bt_value ** const libResultPtr) noexcept
121 const auto privQueryExec = wrap(libPrivQueryExecPtr);
124 auto result = UserCompClsT::query(wrap(libSelfCompClsPtr), privQueryExec, object,
127 *libResultPtr = result.release().libObjPtr();
128 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
129 } catch (const TryAgain&) {
130 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
131 } catch (const UnknownObject&) {
132 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
133 } catch (const std::bad_alloc&) {
134 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
135 } catch (const Error&) {
136 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
138 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
139 unhandledExcLogTag(), unhandledExcLogStr());
140 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
145 template <typename SpecCompClsBridgeT, typename LibTypesT>
146 struct CompClsBridgeWithInputPorts
148 static bt_component_class_port_connected_method_status
149 inputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
150 bt_self_component_port_input * const libSelfCompPortPtr,
151 const bt_port_output * const libOtherPortPtr) noexcept
154 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
155 .inputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
156 } catch (const std::bad_alloc&) {
157 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
158 } catch (const Error&) {
159 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
161 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
162 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
163 unhandledExcLogTag(), unhandledExcLogStr());
164 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
167 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
171 template <typename SpecCompClsBridgeT, typename LibTypesT>
172 struct CompClsBridgeWithOutputPorts
174 static bt_component_class_port_connected_method_status
175 outputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
176 bt_self_component_port_output * const libSelfCompPortPtr,
177 const bt_port_input * const libOtherPortPtr) noexcept
180 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
181 .outputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
182 } catch (const std::bad_alloc&) {
183 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
184 } catch (const Error&) {
185 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
187 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
188 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
189 unhandledExcLogTag(), unhandledExcLogStr());
190 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
193 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
197 struct SrcCompClsLibTypes final
199 using SelfCompCls = bt_self_component_class_source;
200 using SelfComp = bt_self_component_source;
201 using SelfCompCfg = bt_self_component_source_configuration;
204 template <typename UserCompClsT>
205 class SrcCompClsBridge final :
206 public CompClsBridge<UserCompClsT, SrcCompClsLibTypes>,
207 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsLibTypes>
211 struct FltCompClsLibTypes final
213 using SelfCompCls = bt_self_component_class_filter;
214 using SelfComp = bt_self_component_filter;
215 using SelfCompCfg = bt_self_component_filter_configuration;
218 template <typename UserCompClsT>
219 class FltCompClsBridge final :
220 public CompClsBridge<UserCompClsT, FltCompClsLibTypes>,
221 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>,
222 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>
226 struct SinkCompClsLibTypes final
228 using SelfCompCls = bt_self_component_class_sink;
229 using SelfComp = bt_self_component_sink;
230 using SelfCompCfg = bt_self_component_sink_configuration;
233 template <typename UserCompClsT>
234 class SinkCompClsBridge final :
235 CompClsBridge<UserCompClsT, SinkCompClsLibTypes>,
236 CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsLibTypes>
239 using CompClsBridge<UserCompClsT, SinkCompClsLibTypes>::userCompFromLibSelfCompPtr;
242 static bt_component_class_sink_consume_method_status
243 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
246 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
247 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
249 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
251 } catch (const TryAgain&) {
252 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
253 } catch (const std::bad_alloc&) {
254 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
255 } catch (const Error&) {
256 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
258 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
259 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
260 unhandledExcLogTag(), unhandledExcLogStr());
261 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
265 static bt_component_class_sink_graph_is_configured_method_status
266 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
269 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
270 } catch (const std::bad_alloc&) {
271 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
272 } catch (const Error&) {
273 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
275 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
276 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
277 unhandledExcLogTag(), unhandledExcLogStr());
278 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
283 template <typename UserMsgIterT>
284 class MsgIterClsBridge final
288 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
290 return bt2::wrap(libSelfMsgIterPtr).data<UserMsgIterT>();
293 static bt_message_iterator_class_initialize_method_status
294 init(bt_self_message_iterator * const libSelfMsgIterPtr,
295 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
296 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
298 const auto selfMsgIter = bt2::wrap(libSelfMsgIterPtr);
301 const auto msgIter = new UserMsgIterT {selfMsgIter, bt2::wrap(libSelfMsgIterConfigPtr),
302 bt2::wrap(libSelfCompPortPtr)};
304 selfMsgIter.data(*msgIter);
305 } catch (const std::bad_alloc&) {
306 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
307 } catch (const bt2::Error&) {
308 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
310 BT_LOG_WRITE_CUR_LVL(
312 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
313 unhandledExcLogTag(), unhandledExcLogStr());
314 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
317 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
320 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
322 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
325 static bt_message_iterator_class_next_method_status
326 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
327 const uint64_t capacity, uint64_t * const count) noexcept
330 auto msgArray = bt2::ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
331 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
333 msgIter.next(msgArray);
334 *count = msgArray.release();
336 if (G_LIKELY(*count > 0)) {
337 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
339 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
341 } catch (const bt2::TryAgain&) {
342 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
343 } catch (const std::bad_alloc&) {
344 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
345 } catch (const bt2::Error&) {
346 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
348 BT_LOG_WRITE_CUR_LVL(
350 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
351 unhandledExcLogTag(), unhandledExcLogStr());
352 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
356 static bt_message_iterator_class_can_seek_beginning_method_status
357 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
358 bt_bool * const canSeek) noexcept
361 *canSeek = static_cast<bt_bool>(
362 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
363 } catch (const bt2::TryAgain&) {
364 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
365 } catch (const std::bad_alloc&) {
366 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
367 } catch (const bt2::Error&) {
368 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
370 BT_LOG_WRITE_CUR_LVL(
372 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
373 unhandledExcLogTag(), unhandledExcLogStr());
374 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
377 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
380 static bt_message_iterator_class_seek_beginning_method_status
381 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
384 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
385 } catch (const bt2::TryAgain&) {
386 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
387 } catch (const std::bad_alloc&) {
388 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
389 } catch (const bt2::Error&) {
390 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
392 BT_LOG_WRITE_CUR_LVL(
394 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
395 unhandledExcLogTag(), unhandledExcLogStr());
396 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
399 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
402 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
403 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
404 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
407 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
408 .canSeekNsFromOrigin(nsFromOrigin));
409 } catch (const bt2::TryAgain&) {
410 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
411 } catch (const std::bad_alloc&) {
412 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
413 } catch (const bt2::Error&) {
414 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
416 BT_LOG_WRITE_CUR_LVL(
418 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
419 unhandledExcLogTag(), unhandledExcLogStr());
420 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
423 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
426 static bt_message_iterator_class_seek_ns_from_origin_method_status
427 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
428 const std::int64_t nsFromOrigin) noexcept
431 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
432 } catch (const bt2::TryAgain&) {
433 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
434 } catch (const std::bad_alloc&) {
435 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
436 } catch (const bt2::Error&) {
437 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
439 BT_LOG_WRITE_CUR_LVL(
441 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
442 unhandledExcLogTag(), unhandledExcLogStr());
443 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
446 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
450 } /* namespace internal */
452 template <typename UserMessageIteratorT, typename UserComponentT>
453 class UserMessageIterator;
456 * Base class of any user component.
458 * See the specific `bt2::UserSourceComponent`,
459 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
461 template <typename SelfCompT>
464 /* Give a related message iterator access to this logger */
465 template <typename, typename>
466 friend class UserMessageIterator;
469 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
470 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
475 bt2c::CStringView _name() const noexcept
477 return _mSelfComp.name();
480 LoggingLevel _loggingLevel() const noexcept
482 return _mSelfComp.loggingLevel();
485 std::uint64_t _graphMipVersion() const noexcept
487 return _mSelfComp.graphMipVersion();
490 SelfCompT _selfComp() noexcept
495 bt2c::Logger _mLogger;
498 SelfCompT _mSelfComp;
502 * Base class of a user source component `UserComponentT` (CRTP).
504 * `UserComponentT::UserComponentT()` must accept a
505 * `bt2::SelfSourceComponent` parameter, which it needs to forward to
506 * bt2::UserSourceComponent::UserSourceComponent(), and a
507 * `bt2::ConstValue` parameter (initialization parameters).
509 * `UserMessageIteratorT`, the message iterator class to use, must inherit
510 * `UserMessageIterator`.
512 template <typename UserComponentT, typename UserMessageIteratorT>
513 class UserSourceComponent : public UserComponent<SelfSourceComponent>
515 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
516 UserMessageIteratorT>::value,
517 "`UserMessageIteratorT` inherits `UserMessageIterator`");
520 using MessageIterator = UserMessageIteratorT;
523 using _OutputPorts = SelfSourceComponent::OutputPorts;
525 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
526 UserComponent<SelfSourceComponent> {selfComp, logTag}
531 static Value::Shared query(const SelfComponentClass selfCompCls,
532 const PrivateQueryExecutor privQueryExec,
533 const bt2c::CStringView obj, const ConstValue params)
535 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
538 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
539 const ConstValue params, const LoggingLevel loggingLevel,
540 const UnsignedIntegerRangeSet ranges)
542 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
545 void outputPortConnected(const SelfComponentOutputPort outputPort,
546 const ConstInputPort inputPort)
548 static_cast<UserComponentT&>(*this).outputPortConnected(outputPort, inputPort);
553 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
556 throw UnknownObject {};
560 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
561 const UnsignedIntegerRangeSet ranges)
563 ranges.addRange(0, 0);
567 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
571 template <typename DataT>
572 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
574 return this->_selfComp().addOutputPort(name, data);
577 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
579 return this->_selfComp().addOutputPort(name);
582 _OutputPorts _outputPorts() noexcept
584 return this->_selfComp().outputPorts();
589 * Base class of a user filter component `UserComponentT` (CRTP).
591 * `UserComponentT::UserComponentT()` must accept a
592 * `bt2::SelfFilterComponent` parameter, which it needs to forward to
593 * bt2::UserFilterComponent::UserFilterComponent(), and a
594 * `bt2::ConstValue` parameter (initialization parameters).
596 * `UserMessageIteratorT`, the message iterator class to use, must inherit
597 * `UserMessageIterator`.
599 template <typename UserComponentT, typename UserMessageIteratorT>
600 class UserFilterComponent : public UserComponent<SelfFilterComponent>
602 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
603 UserMessageIteratorT>::value,
604 "`UserMessageIteratorT` inherits `UserMessageIterator`");
607 using MessageIterator = UserMessageIteratorT;
610 using _InputPorts = SelfFilterComponent::InputPorts;
611 using _OutputPorts = SelfFilterComponent::OutputPorts;
613 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
614 UserComponent<SelfFilterComponent> {selfComp, logTag}
619 static Value::Shared query(const SelfComponentClass selfCompCls,
620 const PrivateQueryExecutor privQueryExec,
621 const bt2c::CStringView obj, const ConstValue params)
623 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
626 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
627 const ConstValue params, const LoggingLevel loggingLevel,
628 const UnsignedIntegerRangeSet ranges)
630 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
633 void inputPortConnected(const SelfComponentInputPort inputPort,
634 const ConstOutputPort outputPort)
636 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
639 void outputPortConnected(const SelfComponentOutputPort outputPort,
640 const ConstInputPort inputPort)
642 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
647 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
650 throw UnknownObject {};
654 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
655 const UnsignedIntegerRangeSet ranges)
657 ranges.addRange(0, 0);
661 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
666 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
670 template <typename DataT>
671 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
673 return this->_selfComp().addInputPort(name, data);
676 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
678 return this->_selfComp().addInputPort(name);
681 _InputPorts _inputPorts() noexcept
683 return this->_selfComp().inputPorts();
686 template <typename DataT>
687 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
689 return this->_selfComp().addOutputPort(name, data);
692 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
694 return this->_selfComp().addOutputPort(name);
697 _OutputPorts _outputPorts() noexcept
699 return this->_selfComp().outputPorts();
704 * Base class of a user sink component `UserComponentT` (CRTP).
706 * `UserComponentT::UserComponentT()` must accept a
707 * `bt2::SelfSinkComponent` parameter, which it needs to forward to
708 * bt2::UserSinkComponent::UserSinkComponent(), and a `bt2::ConstValue`
709 * parameter (initialization parameters).
711 * `UserComponentT` must implement:
715 * This method returns `true` if the sink component still needs to
716 * consume, or `false` if it's finished.
718 template <typename UserComponentT>
719 class UserSinkComponent : public UserComponent<SelfSinkComponent>
722 using _InputPorts = SelfSinkComponent::InputPorts;
724 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
725 UserComponent<SelfSinkComponent> {selfComp, logTag}
730 static Value::Shared query(const SelfComponentClass selfCompCls,
731 const PrivateQueryExecutor privQueryExec,
732 const bt2c::CStringView obj, const ConstValue params)
734 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
737 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
738 const ConstValue params, const LoggingLevel loggingLevel,
739 const UnsignedIntegerRangeSet ranges)
741 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
744 void graphIsConfigured()
746 static_cast<UserComponentT&>(*this)._graphIsConfigured();
749 void inputPortConnected(const SelfComponentInputPort inputPort,
750 const ConstOutputPort outputPort)
752 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
757 return static_cast<UserComponentT&>(*this)._consume();
762 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
765 throw UnknownObject {};
769 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
770 const UnsignedIntegerRangeSet ranges)
772 ranges.addRange(0, 0);
776 void _graphIsConfigured()
781 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
785 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
787 return this->_selfComp().createMessageIterator(port);
790 template <typename DataT>
791 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
793 return this->_selfComp().addInputPort(name, data);
796 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
798 return this->_selfComp().addInputPort(name);
801 _InputPorts _inputPorts() noexcept
803 return this->_selfComp().inputPorts();
808 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
809 * of which the parent user component class is `UserComponentT`.
811 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
812 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
813 * bt2::UserMessageIterator::UserMessageIterator().
815 * The public next() method below (called by the bridge) implements the
816 * very common pattern of appending messages into the output array, and,
819 * If it catches a `bt2::TryAgain` exception:
820 * If the message array isn't empty, transform this into a success
825 * If it catches an error:
826 * If the message array isn't empty, transform this into a success
827 * (don't throw), but save the error of the current thread and the
828 * type of error to throw the next time the user calls next().
832 * `UserMessageIteratorT` must implement:
834 * void _next(bt2::ConstMessageArray& messages);
836 * This method fills `messages` with at most `messages.capacity()`
837 * messages and may throw `bt2::TryAgain` or a valid error whenever.
838 * Leaving an empty `messages` means the end of iteration.
840 template <typename UserMessageIteratorT, typename UserComponentT>
841 class UserMessageIterator
844 /* Type of `_mExcToThrowType` */
845 enum class _ExcToThrowType
853 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
854 const std::string& logTagSuffix) :
855 _mSelfMsgIter {selfMsgIter},
856 _mLogger {selfMsgIter,
857 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
862 ~UserMessageIterator()
867 void next(bt2::ConstMessageArray& messages)
869 /* Any saved error? Now is the time to throw */
870 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
871 /* Move `_mSavedLibError`, if any, as current thread error */
872 if (_mSavedLibError) {
873 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError);
876 /* Throw the corresponding exception */
877 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
880 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
881 throw bt2::MemoryError {};
886 * When catching some exception below, if our message array
887 * isn't empty, then return immediately before throwing to
888 * provide those messages to downstream.
890 * When catching an error, also save the current thread error,
891 * if any, so that we can restore it later (see the beginning of
894 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
897 this->_userObj()._next(messages);
899 /* We're done: everything below is exception handling */
901 } catch (const bt2::TryAgain&) {
902 if (messages.isEmpty()) {
905 } catch (const std::bad_alloc&) {
906 if (messages.isEmpty()) {
910 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
911 } catch (const bt2::Error&) {
912 if (messages.isEmpty()) {
916 _mExcToThrowType = _ExcToThrowType::ERROR;
919 if (_mExcToThrowType != _ExcToThrowType::NONE) {
921 "An error occurred, but there are {} messages to return: delaying the error reporting.",
923 BT_ASSERT(!_mSavedLibError);
924 _mSavedLibError = bt_current_thread_take_error();
928 bool canSeekBeginning()
931 return this->_userObj()._canSeekBeginning();
937 return this->_userObj()._seekBeginning();
940 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
943 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
946 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
949 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
954 bool _canSeekBeginning() noexcept
960 void _seekBeginning() noexcept
965 bool _canSeekNsFromOrigin(std::int64_t) noexcept
971 void _seekNsFromOrigin(std::int64_t) noexcept
975 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
977 return _mSelfMsgIter.createMessageIterator(port);
980 UserComponentT& _component() noexcept
982 return _mSelfMsgIter.component().template data<UserComponentT>();
985 SelfComponentOutputPort _port() noexcept
987 return _mSelfMsgIter.port();
990 bool _isInterrupted() const noexcept
992 return _mSelfMsgIter.isInterrupted();
996 UserMessageIteratorT& _userObj() noexcept
998 return static_cast<UserMessageIteratorT&>(*this);
1001 void _resetError() noexcept
1003 _mExcToThrowType = _ExcToThrowType::NONE;
1005 if (_mSavedLibError) {
1006 bt_error_release(_mSavedLibError);
1010 SelfMessageIterator _mSelfMsgIter;
1013 * next() may accumulate messages, and then catch an error before
1014 * returning. In that case, it saves the error of the current thread
1015 * here so that it can return its accumulated messages and throw the
1018 * It also saves the type of the exception to throw the next time.
1020 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
1021 const bt_error *_mSavedLibError = nullptr;
1024 bt2c::Logger _mLogger;
1027 } /* namespace bt2 */
1029 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1030 _userComponentClass) \
1031 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1032 _pluginId, _componentClassId, _name, \
1033 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1034 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1035 _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \
1036 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1037 _pluginId, _componentClassId, \
1038 bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \
1039 BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1040 _pluginId, _componentClassId, \
1041 bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1042 BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1043 _pluginId, _componentClassId, \
1044 bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \
1045 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1046 _pluginId, _componentClassId, \
1047 bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \
1048 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1049 _pluginId, _componentClassId, \
1050 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1051 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1052 _pluginId, _componentClassId, \
1053 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1054 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1055 _pluginId, _componentClassId, \
1056 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1057 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1058 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1059 _pluginId, _componentClassId, \
1060 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1061 bt2::internal::MsgIterClsBridge< \
1062 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1064 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1065 _userComponentClass) \
1066 BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1067 _pluginId, _componentClassId, _name, \
1068 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1069 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1070 _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \
1071 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1072 _pluginId, _componentClassId, \
1073 bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \
1074 BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1075 _pluginId, _componentClassId, \
1076 bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1077 BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1078 _pluginId, _componentClassId, \
1079 bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \
1080 BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1081 _pluginId, _componentClassId, \
1082 bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \
1083 BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1084 _pluginId, _componentClassId, \
1085 bt2::internal::FltCompClsBridge<_userComponentClass>::query); \
1086 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1087 _pluginId, _componentClassId, \
1088 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1089 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1090 _pluginId, _componentClassId, \
1091 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1092 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1093 _pluginId, _componentClassId, \
1094 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1095 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1096 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1097 _pluginId, _componentClassId, \
1098 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1099 bt2::internal::MsgIterClsBridge< \
1100 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1102 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1103 _userComponentClass) \
1104 BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \
1105 _pluginId, _componentClassId, _name, \
1106 bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \
1107 BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1108 _pluginId, _componentClassId, \
1109 bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \
1110 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1111 _pluginId, _componentClassId, \
1112 bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \
1113 BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1114 _pluginId, _componentClassId, \
1115 bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1116 BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1117 _pluginId, _componentClassId, \
1118 bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \
1119 BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \
1120 _pluginId, _componentClassId, \
1121 bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \
1122 BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1123 _pluginId, _componentClassId, \
1124 bt2::internal::SinkCompClsBridge<_userComponentClass>::query);
1126 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass) \
1127 BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1129 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass) \
1130 BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1132 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \
1133 BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1135 #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */