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