cpp-common/bt2: use `std::unique_ptr` to manage `UserMessageIterator::_mSavedLibError`
[babeltrace.git] / src / cpp-common / bt2 / component-class-dev.hpp
1 /*
2 * Copyright (c) 2024 EfficiOS, Inc.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #ifndef BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP
9
10 #include <cstdint>
11
12 #include <glib.h>
13
14 #include "cpp-common/bt2c/c-string-view.hpp"
15 #include "cpp-common/bt2c/logging.hpp"
16 #include "cpp-common/vendor/fmt/core.h"
17
18 #include "exc.hpp"
19 #include "internal/comp-cls-bridge.hpp"
20 #include "private-query-executor.hpp"
21 #include "self-component-port.hpp"
22
23 namespace bt2 {
24
25 template <typename UserMessageIteratorT, typename UserComponentT>
26 class UserMessageIterator;
27
28 /*
29 * Base class of any user component.
30 *
31 * See the specific `bt2::UserSourceComponent`,
32 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
33 */
34 template <typename SelfCompT, typename InitDataT, typename QueryDataT>
35 class UserComponent
36 {
37 /* Give a related message iterator access to this logger */
38 template <typename, typename>
39 friend class UserMessageIterator;
40
41 public:
42 using InitData = InitDataT;
43 using QueryData = QueryDataT;
44
45 static constexpr auto description = nullptr;
46 static constexpr auto help = nullptr;
47
48 protected:
49 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
50 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
51 {
52 }
53
54 protected:
55 bt2c::CStringView _name() const noexcept
56 {
57 return _mSelfComp.name();
58 }
59
60 LoggingLevel _loggingLevel() const noexcept
61 {
62 return _mSelfComp.loggingLevel();
63 }
64
65 std::uint64_t _graphMipVersion() const noexcept
66 {
67 return _mSelfComp.graphMipVersion();
68 }
69
70 SelfCompT _selfComp() noexcept
71 {
72 return _mSelfComp;
73 }
74
75 bt2c::Logger _mLogger;
76
77 private:
78 SelfCompT _mSelfComp;
79 };
80
81 /*
82 * Base class of a user source component `UserComponentT` (CRTP).
83 *
84 * `UserComponentT` must define a static member `name` of type
85 * `const char *` to provide the name of the component class.
86 *
87 * `UserComponentT` may define the static members `description` and/or
88 * `help` of type `const char *` to provide the description and/or help
89 * of the component class.
90 *
91 * UserComponentT::UserComponentT() must accept, in this order:
92 *
93 * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward
94 * to bt2::UserSourceComponent::UserSourceComponent().
95 *
96 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
97 *
98 * 3. An `InitDataT *` parameter (the initialization method data).
99 *
100 * `UserMessageIteratorT`, the message iterator class to use, must inherit
101 * `UserMessageIterator`.
102 *
103 * UserComponentT::_query() receives a query method data pointer of type
104 * `QueryDataT *` as its last parameter.
105 */
106 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
107 typename QueryDataT = void>
108 class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT, QueryDataT>
109 {
110 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
111 UserMessageIteratorT>::value,
112 "`UserMessageIteratorT` inherits `UserMessageIterator`");
113
114 public:
115 using MessageIterator = UserMessageIteratorT;
116
117 protected:
118 using _OutputPorts = SelfSourceComponent::OutputPorts;
119
120 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
121 UserComponent<SelfSourceComponent, InitDataT, QueryDataT> {selfComp, logTag}
122 {
123 }
124
125 public:
126 static Value::Shared query(const SelfComponentClass selfCompCls,
127 const PrivateQueryExecutor privQueryExec,
128 const bt2c::CStringView obj, const ConstValue params,
129 QueryDataT * const data)
130 {
131 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
132 }
133
134 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
135 const ConstValue params, const LoggingLevel loggingLevel,
136 const UnsignedIntegerRangeSet ranges)
137 {
138 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
139 }
140
141 void outputPortConnected(const SelfComponentOutputPort outputPort,
142 const ConstInputPort inputPort)
143 {
144 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
145 }
146
147 protected:
148 /* Overloadable */
149 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
150 ConstValue, QueryDataT *)
151 {
152 throw UnknownObject {};
153 }
154
155 /* Overloadable */
156 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
157 const UnsignedIntegerRangeSet ranges)
158 {
159 ranges.addRange(0, 0);
160 }
161
162 /* Overloadable */
163 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
164 {
165 }
166
167 template <typename DataT>
168 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
169 {
170 return this->_selfComp().addOutputPort(name, data);
171 }
172
173 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
174 {
175 return this->_selfComp().addOutputPort(name);
176 }
177
178 _OutputPorts _outputPorts() noexcept
179 {
180 return this->_selfComp().outputPorts();
181 }
182 };
183
184 /*
185 * Base class of a user filter component `UserComponentT` (CRTP).
186 *
187 * `UserComponentT` must define a static member `name` of type
188 * `const char *` to provide the name of the component class.
189 *
190 * `UserComponentT` may define the static members `description` and/or
191 * `help` of type `const char *` to provide the description and/or help
192 * of the component class.
193 *
194 * UserComponentT::UserComponentT() must accept, in this order:
195 *
196 * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward
197 * to bt2::UserFilterComponent::UserFilterComponent().
198 *
199 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
200 *
201 * 3. An `InitDataT *` parameter (the initialization method data).
202 *
203 * `UserMessageIteratorT`, the message iterator class to use, must inherit
204 * `UserMessageIterator`.
205 *
206 * UserComponentT::_query() receives a query method data pointer of type
207 * `QueryDataT *` as its last parameter.
208 */
209 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
210 typename QueryDataT = void>
211 class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT, QueryDataT>
212 {
213 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
214 UserMessageIteratorT>::value,
215 "`UserMessageIteratorT` inherits `UserMessageIterator`");
216
217 public:
218 using MessageIterator = UserMessageIteratorT;
219
220 protected:
221 using _InputPorts = SelfFilterComponent::InputPorts;
222 using _OutputPorts = SelfFilterComponent::OutputPorts;
223
224 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
225 UserComponent<SelfFilterComponent, InitDataT, QueryDataT> {selfComp, logTag}
226 {
227 }
228
229 public:
230 static Value::Shared query(const SelfComponentClass selfCompCls,
231 const PrivateQueryExecutor privQueryExec,
232 const bt2c::CStringView obj, const ConstValue params,
233 QueryDataT * const data)
234 {
235 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
236 }
237
238 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
239 const ConstValue params, const LoggingLevel loggingLevel,
240 const UnsignedIntegerRangeSet ranges)
241 {
242 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
243 }
244
245 void inputPortConnected(const SelfComponentInputPort inputPort,
246 const ConstOutputPort outputPort)
247 {
248 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
249 }
250
251 void outputPortConnected(const SelfComponentOutputPort outputPort,
252 const ConstInputPort inputPort)
253 {
254 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
255 }
256
257 protected:
258 /* Overloadable */
259 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
260 ConstValue, QueryDataT *)
261 {
262 throw UnknownObject {};
263 }
264
265 /* Overloadable */
266 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
267 const UnsignedIntegerRangeSet ranges)
268 {
269 ranges.addRange(0, 0);
270 }
271
272 /* Overloadable */
273 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
274 {
275 }
276
277 /* Overloadable */
278 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
279 {
280 }
281
282 template <typename DataT>
283 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
284 {
285 return this->_selfComp().addInputPort(name, data);
286 }
287
288 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
289 {
290 return this->_selfComp().addInputPort(name);
291 }
292
293 _InputPorts _inputPorts() noexcept
294 {
295 return this->_selfComp().inputPorts();
296 }
297
298 template <typename DataT>
299 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data)
300 {
301 return this->_selfComp().addOutputPort(name, data);
302 }
303
304 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
305 {
306 return this->_selfComp().addOutputPort(name);
307 }
308
309 _OutputPorts _outputPorts() noexcept
310 {
311 return this->_selfComp().outputPorts();
312 }
313 };
314
315 /*
316 * Base class of a user sink component `UserComponentT` (CRTP).
317 *
318 * `UserComponentT` must define a static member `name` of type
319 * `const char *` to provide the name of the component class.
320 *
321 * `UserComponentT` may define the static members `description` and/or
322 * `help` of type `const char *` to provide the description and/or help
323 * of the component class.
324 *
325 * UserComponentT::UserComponentT() must accept, in this order:
326 *
327 * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward
328 * to bt2::UserSinkComponent::UserSinkComponent().
329 *
330 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
331 *
332 * 3. An `InitDataT *` parameter (the initialization method data).
333 *
334 * `UserComponentT` must implement:
335 *
336 * bool _consume();
337 *
338 * This method returns `true` if the sink component still needs to
339 * consume, or `false` if it's finished.
340 *
341 * UserComponentT::_query() receives a query method data pointer of type
342 * `QueryDataT *` as its last parameter.
343
344 */
345 template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void>
346 class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT>
347 {
348 protected:
349 using _InputPorts = SelfSinkComponent::InputPorts;
350
351 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
352 UserComponent<SelfSinkComponent, InitDataT, QueryDataT> {selfComp, logTag}
353 {
354 }
355
356 public:
357 static Value::Shared query(const SelfComponentClass selfCompCls,
358 const PrivateQueryExecutor privQueryExec,
359 const bt2c::CStringView obj, const ConstValue params,
360 QueryDataT * const data)
361 {
362 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
363 }
364
365 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
366 const ConstValue params, const LoggingLevel loggingLevel,
367 const UnsignedIntegerRangeSet ranges)
368 {
369 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
370 }
371
372 void graphIsConfigured()
373 {
374 static_cast<UserComponentT&>(*this)._graphIsConfigured();
375 }
376
377 void inputPortConnected(const SelfComponentInputPort inputPort,
378 const ConstOutputPort outputPort)
379 {
380 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
381 }
382
383 bool consume()
384 {
385 return static_cast<UserComponentT&>(*this)._consume();
386 }
387
388 protected:
389 /* Overloadable */
390 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
391 ConstValue, QueryDataT *)
392 {
393 throw UnknownObject {};
394 }
395
396 /* Overloadable */
397 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
398 const UnsignedIntegerRangeSet ranges)
399 {
400 ranges.addRange(0, 0);
401 }
402
403 /* Overloadable */
404 void _graphIsConfigured()
405 {
406 }
407
408 /* Overloadable */
409 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
410 {
411 }
412
413 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
414 {
415 return this->_selfComp().createMessageIterator(port);
416 }
417
418 template <typename DataT>
419 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data)
420 {
421 return this->_selfComp().addInputPort(name, data);
422 }
423
424 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
425 {
426 return this->_selfComp().addInputPort(name);
427 }
428
429 _InputPorts _inputPorts() noexcept
430 {
431 return this->_selfComp().inputPorts();
432 }
433 };
434
435 /*
436 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
437 * of which the parent user component class is `UserComponentT`.
438 *
439 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
440 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
441 * bt2::UserMessageIterator::UserMessageIterator().
442 *
443 * The public next() method below (called by the bridge) implements the
444 * very common pattern of appending messages into the output array, and,
445 * meanwhile:
446 *
447 * If it catches a `bt2::TryAgain` exception:
448 * If the message array isn't empty, transform this into a success
449 * (don't throw).
450 *
451 * Otherwise rethrow.
452 *
453 * If it catches an error:
454 * If the message array isn't empty, transform this into a success
455 * (don't throw), but save the error of the current thread and the
456 * type of error to throw the next time the user calls next().
457 *
458 * Otherwise rethrow.
459 *
460 * `UserMessageIteratorT` must implement:
461 *
462 * void _next(bt2::ConstMessageArray& messages);
463 *
464 * This method fills `messages` with at most `messages.capacity()`
465 * messages and may throw `bt2::TryAgain` or a valid error whenever.
466 * Leaving an empty `messages` means the end of iteration.
467 */
468 template <typename UserMessageIteratorT, typename UserComponentT>
469 class UserMessageIterator
470 {
471 private:
472 /* Type of `_mExcToThrowType` */
473 enum class _ExcToThrowType
474 {
475 NONE,
476 ERROR,
477 MEM_ERROR,
478 };
479
480 protected:
481 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
482 const std::string& logTagSuffix) :
483 _mSelfMsgIter {selfMsgIter},
484 _mLogger {selfMsgIter,
485 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
486 {
487 }
488
489 public:
490 void next(bt2::ConstMessageArray& messages)
491 {
492 /* Any saved error? Now is the time to throw */
493 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
494 /* Move `_mSavedLibError`, if any, as current thread error */
495 if (_mSavedLibError) {
496 bt_current_thread_move_error(_mSavedLibError.release());
497 }
498
499 /* Throw the corresponding exception */
500 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
501 throw bt2::Error {};
502 } else {
503 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
504 throw bt2::MemoryError {};
505 }
506 }
507
508 /*
509 * When catching some exception below, if our message array
510 * isn't empty, then return immediately before throwing to
511 * provide those messages to downstream.
512 *
513 * When catching an error, also save the current thread error,
514 * if any, so that we can restore it later (see the beginning of
515 * this method).
516 */
517 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
518
519 try {
520 this->_userObj()._next(messages);
521
522 /* We're done: everything below is exception handling */
523 return;
524 } catch (const bt2::TryAgain&) {
525 if (messages.isEmpty()) {
526 throw;
527 }
528 } catch (const std::bad_alloc&) {
529 if (messages.isEmpty()) {
530 throw;
531 }
532
533 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
534 } catch (const bt2::Error&) {
535 if (messages.isEmpty()) {
536 throw;
537 }
538
539 _mExcToThrowType = _ExcToThrowType::ERROR;
540 }
541
542 if (_mExcToThrowType != _ExcToThrowType::NONE) {
543 BT_CPPLOGE(
544 "An error occurred, but there are {} messages to return: delaying the error reporting.",
545 messages.length());
546 BT_ASSERT(!_mSavedLibError);
547 _mSavedLibError.reset(bt_current_thread_take_error());
548 }
549 }
550
551 bool canSeekBeginning()
552 {
553 this->_resetError();
554 return this->_userObj()._canSeekBeginning();
555 }
556
557 void seekBeginning()
558 {
559 this->_resetError();
560 return this->_userObj()._seekBeginning();
561 }
562
563 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
564 {
565 this->_resetError();
566 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
567 }
568
569 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
570 {
571 this->_resetError();
572 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
573 }
574
575 protected:
576 /* Overloadable */
577 bool _canSeekBeginning() noexcept
578 {
579 return false;
580 }
581
582 /* Overloadable */
583 void _seekBeginning() noexcept
584 {
585 }
586
587 /* Overloadable */
588 bool _canSeekNsFromOrigin(std::int64_t) noexcept
589 {
590 return false;
591 }
592
593 /* Overloadable */
594 void _seekNsFromOrigin(std::int64_t) noexcept
595 {
596 }
597
598 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
599 {
600 return _mSelfMsgIter.createMessageIterator(port);
601 }
602
603 UserComponentT& _component() noexcept
604 {
605 return _mSelfMsgIter.component().template data<UserComponentT>();
606 }
607
608 SelfComponentOutputPort _port() noexcept
609 {
610 return _mSelfMsgIter.port();
611 }
612
613 bool _isInterrupted() const noexcept
614 {
615 return _mSelfMsgIter.isInterrupted();
616 }
617
618 private:
619 UserMessageIteratorT& _userObj() noexcept
620 {
621 return static_cast<UserMessageIteratorT&>(*this);
622 }
623
624 void _resetError() noexcept
625 {
626 _mExcToThrowType = _ExcToThrowType::NONE;
627 _mSavedLibError.reset();
628 }
629
630 SelfMessageIterator _mSelfMsgIter;
631
632 /*
633 * next() may accumulate messages, and then catch an error before
634 * returning. In that case, it saves the error of the current thread
635 * here so that it can return its accumulated messages and throw the
636 * next time.
637 *
638 * It also saves the type of the exception to throw the next time.
639 */
640 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
641
642 struct LibErrorDeleter final
643 {
644 void operator()(const bt_error * const error) const noexcept
645 {
646 bt_error_release(error);
647 }
648 };
649
650 std::unique_ptr<const bt_error, LibErrorDeleter> _mSavedLibError;
651
652 protected:
653 bt2c::Logger _mLogger;
654 };
655
656 namespace internal {
657
658 template <typename UserComponentT, typename CompClsBridgeT, typename LibSpecCompClsPtrT,
659 typename AsCompClsFuncT, typename SetInitMethodFuncT, typename SetFinalizeMethodFuncT,
660 typename SetGetSupportedMipVersionsMethodFuncT, typename SetQueryMethodFuncT>
661 void setCompClsCommonProps(
662 LibSpecCompClsPtrT * const libSpecCompClsPtr, AsCompClsFuncT&& asCompClsFunc,
663 SetInitMethodFuncT&& setInitMethodFunc, SetFinalizeMethodFuncT&& setFinalizeMethodFunc,
664 SetGetSupportedMipVersionsMethodFuncT&& setGetSupportedMipVersionsMethodFunc,
665 SetQueryMethodFuncT&& setQueryMethodFunc)
666 {
667 const auto libCompClsPtr = asCompClsFunc(libSpecCompClsPtr);
668
669 if (UserComponentT::description != nullptr) {
670 const auto status =
671 bt_component_class_set_description(libCompClsPtr, UserComponentT::description);
672
673 if (status == BT_COMPONENT_CLASS_SET_DESCRIPTION_STATUS_MEMORY_ERROR) {
674 throw MemoryError {};
675 }
676 }
677
678 if (UserComponentT::help != nullptr) {
679 const auto status = bt_component_class_set_help(libCompClsPtr, UserComponentT::help);
680
681 if (status == BT_COMPONENT_CLASS_SET_HELP_STATUS_MEMORY_ERROR) {
682 throw MemoryError {};
683 }
684 }
685
686 {
687 const auto status = setInitMethodFunc(libSpecCompClsPtr, CompClsBridgeT::init);
688
689 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
690 }
691
692 {
693 const auto status = setFinalizeMethodFunc(libSpecCompClsPtr, CompClsBridgeT::finalize);
694
695 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
696 }
697
698 {
699 const auto status = setGetSupportedMipVersionsMethodFunc(
700 libSpecCompClsPtr, CompClsBridgeT::getSupportedMipVersions);
701
702 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
703 }
704
705 {
706 const auto status = setQueryMethodFunc(libSpecCompClsPtr, CompClsBridgeT::query);
707
708 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
709 }
710 }
711
712 template <typename MsgIterClsBridgeT>
713 bt_message_iterator_class *createLibMsgIterCls()
714 {
715 const auto libMsgIterClsPtr = bt_message_iterator_class_create(MsgIterClsBridgeT::next);
716
717 if (!libMsgIterClsPtr) {
718 throw MemoryError {};
719 }
720
721 {
722 const auto status = bt_message_iterator_class_set_initialize_method(
723 libMsgIterClsPtr, MsgIterClsBridgeT::init);
724
725 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
726 }
727
728 {
729 const auto status = bt_message_iterator_class_set_finalize_method(
730 libMsgIterClsPtr, MsgIterClsBridgeT::finalize);
731
732 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
733 }
734
735 return libMsgIterClsPtr;
736 }
737
738 template <typename UserComponentT>
739 bt_component_class_source *createSourceCompCls()
740 {
741 static_assert(
742 std::is_base_of<UserSourceComponent<
743 UserComponentT, typename UserComponentT::MessageIterator,
744 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
745 UserComponentT>::value,
746 "`UserComponentT` inherits `UserSourceComponent`");
747
748 using CompClsBridge = internal::SrcCompClsBridge<UserComponentT>;
749 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
750
751 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
752 const auto libCompClsPtr =
753 bt_component_class_source_create(UserComponentT::name, libMsgIterClsPtr);
754
755 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
756
757 if (!libCompClsPtr) {
758 throw MemoryError {};
759 }
760
761 setCompClsCommonProps<UserComponentT, CompClsBridge>(
762 libCompClsPtr, bt_component_class_source_as_component_class,
763 bt_component_class_source_set_initialize_method,
764 bt_component_class_source_set_finalize_method,
765 bt_component_class_source_set_get_supported_mip_versions_method,
766 bt_component_class_source_set_query_method);
767
768 {
769 const auto status = bt_component_class_source_set_output_port_connected_method(
770 libCompClsPtr, CompClsBridge::outputPortConnected);
771
772 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
773 }
774
775 return libCompClsPtr;
776 }
777
778 template <typename UserComponentT>
779 bt_component_class_filter *createFilterCompCls()
780 {
781 static_assert(
782 std::is_base_of<UserFilterComponent<
783 UserComponentT, typename UserComponentT::MessageIterator,
784 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
785 UserComponentT>::value,
786 "`UserComponentT` inherits `UserFilterComponent`");
787
788 using CompClsBridge = internal::FltCompClsBridge<UserComponentT>;
789 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
790
791 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
792 const auto libCompClsPtr =
793 bt_component_class_filter_create(UserComponentT::name, libMsgIterClsPtr);
794
795 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
796
797 if (!libCompClsPtr) {
798 throw MemoryError {};
799 }
800
801 setCompClsCommonProps<UserComponentT, CompClsBridge>(
802 libCompClsPtr, bt_component_class_filter_as_component_class,
803 bt_component_class_filter_set_initialize_method,
804 bt_component_class_filter_set_finalize_method,
805 bt_component_class_filter_set_get_supported_mip_versions_method,
806 bt_component_class_filter_set_query_method);
807
808 {
809 const auto status = bt_component_class_filter_set_input_port_connected_method(
810 libCompClsPtr, CompClsBridge::inputPortConnected);
811
812 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
813 }
814
815 {
816 const auto status = bt_component_class_filter_set_output_port_connected_method(
817 libCompClsPtr, CompClsBridge::outputPortConnected);
818
819 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
820 }
821
822 return libCompClsPtr;
823 }
824
825 template <typename UserComponentT>
826 bt_component_class_sink *createSinkCompCls()
827 {
828 static_assert(
829 std::is_base_of<UserSinkComponent<UserComponentT, typename UserComponentT::InitData,
830 typename UserComponentT::QueryData>,
831 UserComponentT>::value,
832 "`UserComponentT` inherits `UserSinkComponent`");
833
834 using CompClsBridge = internal::SinkCompClsBridge<UserComponentT>;
835
836 const auto libCompClsPtr =
837 bt_component_class_sink_create(UserComponentT::name, CompClsBridge::consume);
838
839 if (!libCompClsPtr) {
840 throw MemoryError {};
841 }
842
843 setCompClsCommonProps<UserComponentT, CompClsBridge>(
844 libCompClsPtr, bt_component_class_sink_as_component_class,
845 bt_component_class_sink_set_initialize_method, bt_component_class_sink_set_finalize_method,
846 bt_component_class_sink_set_get_supported_mip_versions_method,
847 bt_component_class_sink_set_query_method);
848
849 {
850 const auto status = bt_component_class_sink_set_graph_is_configured_method(
851 libCompClsPtr, CompClsBridge::graphIsConfigured);
852
853 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
854 }
855
856 {
857 const auto status = bt_component_class_sink_set_input_port_connected_method(
858 libCompClsPtr, CompClsBridge::inputPortConnected);
859
860 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
861 }
862
863 return libCompClsPtr;
864 }
865
866 } /* namespace internal */
867 } /* namespace bt2 */
868
869 #endif /* BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP */
This page took 0.048167 seconds and 4 git commands to generate.