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/logging.hpp"
18 #include "cpp-common/vendor/fmt/core.h"
26 constexpr const char *unhandledExcLogStr() noexcept
28 return "Unhandled exception.";
31 constexpr const char *unhandledExcLogTag() noexcept
33 return "PLUGIN-DEV-HPP";
37 * Base class of any component class bridge.
39 * `UserCompClsT` is the actual C++ user component class and `LibTypesT`
40 * is a structure offering the following specific library types:
43 * Self component class.
49 * Self component configuration.
51 template <typename UserCompClsT, typename LibTypesT>
55 using _LibSelfCompPtr = typename LibTypesT::SelfComp *;
58 static UserCompClsT& userCompFromLibSelfCompPtr(const _LibSelfCompPtr libSelfCompPtr) noexcept
60 return wrap(libSelfCompPtr).template data<UserCompClsT>();
63 static bt_component_class_initialize_method_status init(const _LibSelfCompPtr libSelfCompPtr,
64 typename LibTypesT::SelfCompCfg *,
65 const bt_value * const libParamsPtr,
68 const auto selfComp = wrap(libSelfCompPtr);
71 const auto comp = new UserCompClsT {selfComp, wrap(libParamsPtr).asMap()};
74 } catch (const std::bad_alloc&) {
75 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
76 } catch (const Error&) {
77 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
79 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(selfComp.loggingLevel()),
80 unhandledExcLogTag(), unhandledExcLogStr());
81 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
84 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
87 static void finalize(const _LibSelfCompPtr libSelfCompPtr) noexcept
89 delete &userCompFromLibSelfCompPtr(libSelfCompPtr);
92 static bt_component_class_get_supported_mip_versions_method_status
93 getSupportedMipVersions(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
94 const bt_value * const libParamsPtr, void *,
95 const bt_logging_level logLevel,
96 bt_integer_range_set_unsigned * const libSupportedVersionsPtr) noexcept
99 UserCompClsT::getSupportedMipVersions(wrap(libSelfCompClsPtr), wrap(libParamsPtr),
100 static_cast<LoggingLevel>(logLevel),
101 wrap(libSupportedVersionsPtr));
102 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_OK;
103 } catch (const std::bad_alloc&) {
104 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_MEMORY_ERROR;
105 } catch (const Error&) {
106 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
108 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(logLevel), unhandledExcLogTag(),
109 unhandledExcLogStr());
110 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
114 static bt_component_class_query_method_status
115 query(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
116 bt_private_query_executor * const libPrivQueryExecPtr, const char * const object,
117 const bt_value * const libParamsPtr, void *,
118 const bt_value ** const libResultPtr) noexcept
120 const auto privQueryExec = wrap(libPrivQueryExecPtr);
123 auto result = UserCompClsT::query(wrap(libSelfCompClsPtr), privQueryExec, object,
126 *libResultPtr = result.release().libObjPtr();
127 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
128 } catch (const TryAgain&) {
129 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
130 } catch (const UnknownObject&) {
131 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
132 } catch (const std::bad_alloc&) {
133 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
134 } catch (const Error&) {
135 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
137 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
138 unhandledExcLogTag(), unhandledExcLogStr());
139 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
144 template <typename SpecCompClsBridgeT, typename LibTypesT>
145 struct CompClsBridgeWithInputPorts
147 static bt_component_class_port_connected_method_status
148 inputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
149 bt_self_component_port_input * const libSelfCompPortPtr,
150 const bt_port_output * const libOtherPortPtr) noexcept
153 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
154 .inputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
155 } catch (const std::bad_alloc&) {
156 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
157 } catch (const Error&) {
158 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
160 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
161 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
162 unhandledExcLogTag(), unhandledExcLogStr());
163 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
166 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
170 template <typename SpecCompClsBridgeT, typename LibTypesT>
171 struct CompClsBridgeWithOutputPorts
173 static bt_component_class_port_connected_method_status
174 outputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
175 bt_self_component_port_output * const libSelfCompPortPtr,
176 const bt_port_input * const libOtherPortPtr) noexcept
179 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
180 .outputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
181 } catch (const std::bad_alloc&) {
182 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
183 } catch (const Error&) {
184 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
186 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
187 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
188 unhandledExcLogTag(), unhandledExcLogStr());
189 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
192 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
196 struct SrcCompClsLibTypes final
198 using SelfCompCls = bt_self_component_class_source;
199 using SelfComp = bt_self_component_source;
200 using SelfCompCfg = bt_self_component_source_configuration;
203 template <typename UserCompClsT>
204 class SrcCompClsBridge final :
205 public CompClsBridge<UserCompClsT, SrcCompClsLibTypes>,
206 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsLibTypes>
210 struct FltCompClsLibTypes final
212 using SelfCompCls = bt_self_component_class_filter;
213 using SelfComp = bt_self_component_filter;
214 using SelfCompCfg = bt_self_component_filter_configuration;
217 template <typename UserCompClsT>
218 class FltCompClsBridge final :
219 public CompClsBridge<UserCompClsT, FltCompClsLibTypes>,
220 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>,
221 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>
225 struct SinkCompClsLibTypes final
227 using SelfCompCls = bt_self_component_class_sink;
228 using SelfComp = bt_self_component_sink;
229 using SelfCompCfg = bt_self_component_sink_configuration;
232 template <typename UserCompClsT>
233 class SinkCompClsBridge final :
234 CompClsBridge<UserCompClsT, SinkCompClsLibTypes>,
235 CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsLibTypes>
238 using CompClsBridge<UserCompClsT, SinkCompClsLibTypes>::userCompFromLibSelfCompPtr;
241 static bt_component_class_sink_consume_method_status
242 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
245 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
246 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
248 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
250 } catch (const TryAgain&) {
251 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
252 } catch (const std::bad_alloc&) {
253 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
254 } catch (const Error&) {
255 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
257 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
258 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
259 unhandledExcLogTag(), unhandledExcLogStr());
260 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
264 static bt_component_class_sink_graph_is_configured_method_status
265 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
268 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
269 } catch (const std::bad_alloc&) {
270 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
271 } catch (const Error&) {
272 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
274 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
275 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
276 unhandledExcLogTag(), unhandledExcLogStr());
277 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
282 template <typename UserMsgIterT>
283 class MsgIterClsBridge final
287 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
289 return bt2::wrap(libSelfMsgIterPtr).data<UserMsgIterT>();
292 static bt_message_iterator_class_initialize_method_status
293 init(bt_self_message_iterator * const libSelfMsgIterPtr,
294 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
295 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
297 const auto selfMsgIter = bt2::wrap(libSelfMsgIterPtr);
300 const auto msgIter = new UserMsgIterT {selfMsgIter, bt2::wrap(libSelfMsgIterConfigPtr),
301 bt2::wrap(libSelfCompPortPtr)};
303 selfMsgIter.data(*msgIter);
304 } catch (const std::bad_alloc&) {
305 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
306 } catch (const bt2::Error&) {
307 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
309 BT_LOG_WRITE_CUR_LVL(
311 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
312 unhandledExcLogTag(), unhandledExcLogStr());
313 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
316 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
319 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
321 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
324 static bt_message_iterator_class_next_method_status
325 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
326 const uint64_t capacity, uint64_t * const count) noexcept
329 auto msgArray = bt2::ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
330 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
332 msgIter.next(msgArray);
333 *count = msgArray.release();
335 if (G_LIKELY(*count > 0)) {
336 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
338 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
340 } catch (const bt2::TryAgain&) {
341 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
342 } catch (const std::bad_alloc&) {
343 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
344 } catch (const bt2::Error&) {
345 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
347 BT_LOG_WRITE_CUR_LVL(
349 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
350 unhandledExcLogTag(), unhandledExcLogStr());
351 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
355 static bt_message_iterator_class_can_seek_beginning_method_status
356 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
357 bt_bool * const canSeek) noexcept
360 *canSeek = static_cast<bt_bool>(
361 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
362 } catch (const bt2::TryAgain&) {
363 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
364 } catch (const std::bad_alloc&) {
365 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
366 } catch (const bt2::Error&) {
367 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
369 BT_LOG_WRITE_CUR_LVL(
371 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
372 unhandledExcLogTag(), unhandledExcLogStr());
373 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
376 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
379 static bt_message_iterator_class_seek_beginning_method_status
380 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
383 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
384 } catch (const bt2::TryAgain&) {
385 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
386 } catch (const std::bad_alloc&) {
387 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
388 } catch (const bt2::Error&) {
389 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
391 BT_LOG_WRITE_CUR_LVL(
393 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
394 unhandledExcLogTag(), unhandledExcLogStr());
395 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
398 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
401 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
402 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
403 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
406 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
407 .canSeekNsFromOrigin(nsFromOrigin));
408 } catch (const bt2::TryAgain&) {
409 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
410 } catch (const std::bad_alloc&) {
411 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
412 } catch (const bt2::Error&) {
413 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
415 BT_LOG_WRITE_CUR_LVL(
417 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
418 unhandledExcLogTag(), unhandledExcLogStr());
419 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
422 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
425 static bt_message_iterator_class_seek_ns_from_origin_method_status
426 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
427 const std::int64_t nsFromOrigin) noexcept
430 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
431 } catch (const bt2::TryAgain&) {
432 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
433 } catch (const std::bad_alloc&) {
434 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
435 } catch (const bt2::Error&) {
436 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
438 BT_LOG_WRITE_CUR_LVL(
440 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
441 unhandledExcLogTag(), unhandledExcLogStr());
442 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
445 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
449 } /* namespace internal */
451 template <typename UserMessageIteratorT, typename UserComponentT>
452 class UserMessageIterator;
455 * Base class of any user component.
457 * See the specific `bt2::UserSourceComponent`,
458 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
460 template <typename SelfCompT>
463 /* Give a related message iterator access to this logger */
464 template <typename, typename>
465 friend class UserMessageIterator;
468 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
469 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
474 const char *_name() const noexcept
476 return _mSelfComp.name();
479 LoggingLevel _loggingLevel() const noexcept
481 return _mSelfComp.loggingLevel();
484 std::uint64_t _graphMipVersion() const noexcept
486 return _mSelfComp.graphMipVersion();
489 SelfCompT _selfComp() noexcept
494 bt2c::Logger _mLogger;
497 SelfCompT _mSelfComp;
501 * Base class of a user source component `UserComponentT` (CRTP).
503 * `UserComponentT::UserComponentT()` must accept a
504 * `bt2::SelfSourceComponent` parameter, which it needs to forward to
505 * bt2::UserSourceComponent::UserSourceComponent(), and a
506 * `bt2::ConstValue` parameter (initialization parameters).
508 template <typename UserComponentT>
509 class UserSourceComponent : public UserComponent<SelfSourceComponent>
512 using _OutputPorts = SelfSourceComponent::OutputPorts;
514 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
515 UserComponent<SelfSourceComponent> {selfComp, logTag}
520 static Value::Shared query(const SelfComponentClass selfCompCls,
521 const PrivateQueryExecutor privQueryExec, const char * const obj,
522 const ConstValue params)
524 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
527 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
528 const ConstValue params, const LoggingLevel loggingLevel,
529 const UnsignedIntegerRangeSet ranges)
531 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
534 void outputPortConnected(const SelfComponentOutputPort outputPort,
535 const ConstInputPort inputPort)
537 static_cast<UserComponentT&>(*this).outputPortConnected(outputPort, inputPort);
542 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, const char *, ConstValue)
544 throw UnknownObject {};
548 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
549 const UnsignedIntegerRangeSet ranges)
551 ranges.addRange(0, 0);
555 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
559 template <typename DataT>
560 _OutputPorts::Port _addOutputPort(const char * const name, DataT * const data)
562 return this->_selfComp().addOutputPort(name, data);
565 _OutputPorts::Port _addOutputPort(const char *name)
567 return this->_selfComp().addOutputPort(name);
570 template <typename DataT>
571 _OutputPorts::Port _addOutputPort(const std::string& name, DataT * const data)
573 return this->_selfComp().addOutputPort(name, data);
576 _OutputPorts::Port _addOutputPort(const std::string& name)
578 return this->_selfComp().addOutputPort(name);
581 _OutputPorts _outputPorts() noexcept
583 return this->_selfComp().outputPorts();
588 * Base class of a user filter component `UserComponentT` (CRTP).
590 * `UserComponentT::UserComponentT()` must accept a
591 * `bt2::SelfFilterComponent` parameter, which it needs to forward to
592 * bt2::UserFilterComponent::UserFilterComponent(), and a
593 * `bt2::ConstValue` parameter (initialization parameters).
595 template <typename UserComponentT>
596 class UserFilterComponent : public UserComponent<SelfFilterComponent>
599 using _InputPorts = SelfFilterComponent::InputPorts;
600 using _OutputPorts = SelfFilterComponent::OutputPorts;
602 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
603 UserComponent<SelfFilterComponent> {selfComp, logTag}
608 static Value::Shared query(const SelfComponentClass selfCompCls,
609 const PrivateQueryExecutor privQueryExec, const char * const obj,
610 const ConstValue params)
612 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
615 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
616 const ConstValue params, const LoggingLevel loggingLevel,
617 const UnsignedIntegerRangeSet ranges)
619 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
622 void inputPortConnected(const SelfComponentInputPort inputPort,
623 const ConstOutputPort outputPort)
625 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
628 void outputPortConnected(const SelfComponentOutputPort outputPort,
629 const ConstInputPort inputPort)
631 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
636 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, const char *, ConstValue)
638 throw UnknownObject {};
642 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
643 const UnsignedIntegerRangeSet ranges)
645 ranges.addRange(0, 0);
649 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
654 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
658 template <typename DataT>
659 _OutputPorts::Port _addInputPort(const char * const name, DataT * const data)
661 return this->_selfComp().addInputPort(name, data);
664 _InputPorts::Port _addInputPort(const char *name)
666 return this->_selfComp().addInputPort(name);
669 template <typename DataT>
670 _InputPorts::Port _addInputPort(const std::string& name, DataT * const data)
672 return this->_selfComp().addInputPort(name, data);
675 _InputPorts::Port _addInputPort(const std::string& name)
677 return this->_selfComp().addInputPort(name);
680 _InputPorts _inputPorts() noexcept
682 return this->_selfComp().inputPorts();
685 template <typename DataT>
686 _OutputPorts::Port _addOutputPort(const char * const name, DataT * const data)
688 return this->_selfComp().addOutputPort(name, data);
691 _OutputPorts::Port _addOutputPort(const char *name)
693 return this->_selfComp().addOutputPort(name);
696 template <typename DataT>
697 _OutputPorts::Port _addOutputPort(const std::string& name, DataT * const data)
699 return this->_selfComp().addOutputPort(name, data);
702 _OutputPorts::Port _addOutputPort(const std::string& name)
704 return this->_selfComp().addOutputPort(name);
707 _OutputPorts _outputPorts() noexcept
709 return this->_selfComp().outputPorts();
714 * Base class of a user sink component `UserComponentT` (CRTP).
716 * `UserComponentT::UserComponentT()` must accept a
717 * `bt2::SelfSinkComponent` parameter, which it needs to forward to
718 * bt2::UserSinkComponent::UserSinkComponent(), and a `bt2::ConstValue`
719 * parameter (initialization parameters).
721 * `UserComponentT` must implement:
725 * This method returns `true` if the sink component still needs to
726 * consume, or `false` if it's finished.
728 template <typename UserComponentT>
729 class UserSinkComponent : public UserComponent<SelfSinkComponent>
732 using _InputPorts = SelfSinkComponent::InputPorts;
734 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
735 UserComponent<SelfSinkComponent> {selfComp, logTag}
740 static Value::Shared query(const SelfComponentClass selfCompCls,
741 const PrivateQueryExecutor privQueryExec, const char * const obj,
742 const ConstValue params)
744 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params);
747 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
748 const ConstValue params, const LoggingLevel loggingLevel,
749 const UnsignedIntegerRangeSet ranges)
751 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
754 void graphIsConfigured()
756 static_cast<UserComponentT&>(*this)._graphIsConfigured();
759 void inputPortConnected(const SelfComponentInputPort inputPort,
760 const ConstOutputPort outputPort)
762 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
767 return static_cast<UserComponentT&>(*this)._consume();
772 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, const char *, ConstValue)
774 throw UnknownObject {};
778 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
779 const UnsignedIntegerRangeSet ranges)
781 ranges.addRange(0, 0);
785 void _graphIsConfigured()
790 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
794 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
796 return this->_selfComp().createMessageIterator(port);
799 template <typename DataT>
800 _InputPorts::Port _addInputPort(const char * const name, DataT * const data)
802 return this->_selfComp().addInputPort(name, data);
805 _InputPorts::Port _addInputPort(const char *name)
807 return this->_selfComp().addInputPort(name);
810 template <typename DataT>
811 _InputPorts::Port _addInputPort(const std::string& name, DataT * const data)
813 return this->_selfComp().addInputPort(name, data);
816 _InputPorts::Port _addInputPort(const std::string& name)
818 return this->_selfComp().addInputPort(name);
821 _InputPorts _inputPorts() noexcept
823 return this->_selfComp().inputPorts();
828 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
829 * of which the parent user component class is `UserComponentT`.
831 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
832 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
833 * bt2::UserMessageIterator::UserMessageIterator().
835 * The public next() method below (called by the bridge) implements the
836 * very common pattern of appending messages into the output array, and,
839 * If it catches a `bt2::TryAgain` exception:
840 * If the message array isn't empty, transform this into a success
845 * If it catches an error:
846 * If the message array isn't empty, transform this into a success
847 * (don't throw), but save the error of the current thread and the
848 * type of error to throw the next time the user calls next().
852 * `UserMessageIteratorT` must implement:
854 * void _next(bt2::ConstMessageArray& messages);
856 * This method fills `messages` with at most `messages.capacity()`
857 * messages and may throw `bt2::TryAgain` or a valid error whenever.
858 * Leaving an empty `messages` means the end of iteration.
860 template <typename UserMessageIteratorT, typename UserComponentT>
861 class UserMessageIterator
864 /* Type of `_mExcToThrowType` */
865 enum class _ExcToThrowType
873 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
874 const std::string& logTagSuffix) :
875 _mSelfMsgIter {selfMsgIter},
876 _mLogger {selfMsgIter,
877 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
882 ~UserMessageIterator()
887 void next(bt2::ConstMessageArray& messages)
889 /* Any saved error? Now is the time to throw */
890 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
891 /* Move `_mSavedLibError`, if any, as current thread error */
892 if (_mSavedLibError) {
893 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError);
896 /* Throw the corresponding exception */
897 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
900 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
901 throw bt2::MemoryError {};
906 * When catching some exception below, if our message array
907 * isn't empty, then return immediately before throwing to
908 * provide those messages to downstream.
910 * When catching an error, also save the current thread error,
911 * if any, so that we can restore it later (see the beginning of
914 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
917 this->_userObj()._next(messages);
919 /* We're done: everything below is exception handling */
921 } catch (const bt2::TryAgain&) {
922 if (messages.isEmpty()) {
925 } catch (const std::bad_alloc&) {
926 if (messages.isEmpty()) {
930 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
931 } catch (const bt2::Error&) {
932 if (messages.isEmpty()) {
936 _mExcToThrowType = _ExcToThrowType::ERROR;
939 if (_mExcToThrowType != _ExcToThrowType::NONE) {
941 "An error occurred, but there are {} messages to return: delaying the error reporting.",
943 BT_ASSERT(!_mSavedLibError);
944 _mSavedLibError = bt_current_thread_take_error();
948 bool canSeekBeginning()
951 return this->_userObj()._canSeekBeginning();
957 return this->_userObj()._seekBeginning();
960 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
963 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
966 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
969 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
974 bool _canSeekBeginning() noexcept
980 void _seekBeginning() noexcept
985 bool _canSeekNsFromOrigin(std::int64_t) noexcept
991 void _seekNsFromOrigin(std::int64_t) noexcept
995 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
997 return _mSelfMsgIter.createMessageIterator(port);
1000 UserComponentT& _component() noexcept
1002 return _mSelfMsgIter.component().template data<UserComponentT>();
1005 SelfComponentOutputPort _port() noexcept
1007 return _mSelfMsgIter.port();
1010 bool _isInterrupted() const noexcept
1012 return _mSelfMsgIter.isInterrupted();
1016 UserMessageIteratorT& _userObj() noexcept
1018 return static_cast<UserMessageIteratorT&>(*this);
1021 void _resetError() noexcept
1023 _mExcToThrowType = _ExcToThrowType::NONE;
1025 if (_mSavedLibError) {
1026 bt_error_release(_mSavedLibError);
1030 SelfMessageIterator _mSelfMsgIter;
1033 * next() may accumulate messages, and then catch an error before
1034 * returning. In that case, it saves the error of the current thread
1035 * here so that it can return its accumulated messages and throw the
1038 * It also saves the type of the exception to throw the next time.
1040 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
1041 const bt_error *_mSavedLibError = nullptr;
1044 bt2c::Logger _mLogger;
1047 } /* namespace bt2 */
1049 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1050 _pluginId, _componentClassId, _name, _userComponentClass, _userMessageIteratorClass) \
1051 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1052 _pluginId, _componentClassId, _name, \
1053 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::next); \
1054 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1055 _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \
1056 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1057 _pluginId, _componentClassId, \
1058 bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \
1059 BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1060 _pluginId, _componentClassId, \
1061 bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1062 BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1063 _pluginId, _componentClassId, \
1064 bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \
1065 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1066 _pluginId, _componentClassId, \
1067 bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \
1068 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1069 _pluginId, _componentClassId, \
1070 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::init); \
1071 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1072 _pluginId, _componentClassId, \
1073 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::finalize); \
1074 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1075 _pluginId, _componentClassId, \
1076 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::seekBeginning, \
1077 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::canSeekBeginning); \
1078 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1079 _pluginId, _componentClassId, \
1080 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::seekNsFromOrigin, \
1081 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::canSeekNsFromOrigin);
1083 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1084 _pluginId, _componentClassId, _name, _userComponentClass, _userMessageIteratorClass) \
1085 BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1086 _pluginId, _componentClassId, _name, \
1087 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::next); \
1088 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1089 _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \
1090 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1091 _pluginId, _componentClassId, \
1092 bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \
1093 BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1094 _pluginId, _componentClassId, \
1095 bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1096 BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1097 _pluginId, _componentClassId, \
1098 bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \
1099 BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1100 _pluginId, _componentClassId, \
1101 bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \
1102 BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1103 _pluginId, _componentClassId, \
1104 bt2::internal::FltCompClsBridge<_userComponentClass>::query); \
1105 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1106 _pluginId, _componentClassId, \
1107 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::init); \
1108 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1109 _pluginId, _componentClassId, \
1110 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::finalize); \
1111 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1112 _pluginId, _componentClassId, \
1113 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::seekBeginning, \
1114 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::canSeekBeginning); \
1115 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1116 _pluginId, _componentClassId, \
1117 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::seekNsFromOrigin, \
1118 bt2::internal::MsgIterClsBridge<_userMessageIteratorClass>::canSeekNsFromOrigin);
1120 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1121 _userComponentClass) \
1122 BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \
1123 _pluginId, _componentClassId, _name, \
1124 bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \
1125 BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1126 _pluginId, _componentClassId, \
1127 bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \
1128 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1129 _pluginId, _componentClassId, \
1130 bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \
1131 BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1132 _pluginId, _componentClassId, \
1133 bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1134 BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1135 _pluginId, _componentClassId, \
1136 bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \
1137 BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \
1138 _pluginId, _componentClassId, \
1139 bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \
1140 BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1141 _pluginId, _componentClassId, \
1142 bt2::internal::SinkCompClsBridge<_userComponentClass>::query);
1144 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass, \
1145 _userMessageIteratorClass) \
1146 BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass, \
1147 _userMessageIteratorClass)
1149 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass, \
1150 _userMessageIteratorClass) \
1151 BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass, \
1152 _userMessageIteratorClass)
1154 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \
1155 BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1157 #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */