cpp-common/bt2: remove extraneous `protected`
[babeltrace.git] / src / cpp-common / bt2 / component-class-dev.hpp
CommitLineData
212313d9
SM
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"
ee137c4e 19#include "internal/comp-cls-bridge.hpp"
212313d9
SM
20#include "private-query-executor.hpp"
21#include "self-component-port.hpp"
22
23namespace bt2 {
24
25template <typename UserMessageIteratorT, typename UserComponentT>
26class UserMessageIterator;
27
28/*
29 * Base class of any user component.
30 *
31 * See the specific `bt2::UserSourceComponent`,
32 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
33 */
34template <typename SelfCompT, typename InitDataT, typename QueryDataT>
35class UserComponent
36{
37 /* Give a related message iterator access to this logger */
38 template <typename, typename>
39 friend class UserMessageIterator;
40
41public:
42 using InitData = InitDataT;
43 using QueryData = QueryDataT;
44
ee137c4e
PP
45 static constexpr auto description = nullptr;
46 static constexpr auto help = nullptr;
47
212313d9
SM
48protected:
49 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
50 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
51 {
52 }
53
212313d9
SM
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
76private:
77 SelfCompT _mSelfComp;
78};
79
80/*
81 * Base class of a user source component `UserComponentT` (CRTP).
82 *
ee137c4e
PP
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 *
212313d9
SM
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 */
105template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
106 typename QueryDataT = void>
107class 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
113public:
114 using MessageIterator = UserMessageIteratorT;
115
116protected:
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
124public:
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 ConstValue 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
146protected:
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, ConstValue, 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 *
ee137c4e
PP
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 *
212313d9
SM
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 */
208template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
209 typename QueryDataT = void>
210class 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
216public:
217 using MessageIterator = UserMessageIteratorT;
218
219protected:
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
228public:
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 ConstValue 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
256protected:
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, ConstValue, 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 *
ee137c4e
PP
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 *
212313d9
SM
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 */
344template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void>
345class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT>
346{
347protected:
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
355public:
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 ConstValue 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
387protected:
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, ConstValue, 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 */
467template <typename UserMessageIteratorT, typename UserComponentT>
468class UserMessageIterator
469{
470private:
471 /* Type of `_mExcToThrowType` */
472 enum class _ExcToThrowType
473 {
474 NONE,
475 ERROR,
476 MEM_ERROR,
477 };
478
479protected:
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
488public:
212313d9
SM
489 void next(bt2::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) {
ea003032 495 bt_current_thread_move_error(_mSavedLibError.release());
212313d9
SM
496 }
497
498 /* Throw the corresponding exception */
499 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
500 throw bt2::Error {};
501 } else {
502 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
503 throw bt2::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 bt2::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::MEM_ERROR;
533 } catch (const bt2::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);
ea003032 546 _mSavedLibError.reset(bt_current_thread_take_error());
212313d9
SM
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
574protected:
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 UserComponentT& _component() noexcept
603 {
604 return _mSelfMsgIter.component().template data<UserComponentT>();
605 }
606
607 SelfComponentOutputPort _port() noexcept
608 {
609 return _mSelfMsgIter.port();
610 }
611
612 bool _isInterrupted() const noexcept
613 {
614 return _mSelfMsgIter.isInterrupted();
615 }
616
617private:
618 UserMessageIteratorT& _userObj() noexcept
619 {
620 return static_cast<UserMessageIteratorT&>(*this);
621 }
622
623 void _resetError() noexcept
624 {
625 _mExcToThrowType = _ExcToThrowType::NONE;
ea003032 626 _mSavedLibError.reset();
212313d9
SM
627 }
628
629 SelfMessageIterator _mSelfMsgIter;
630
631 /*
632 * next() may accumulate messages, and then catch an error before
633 * returning. In that case, it saves the error of the current thread
634 * here so that it can return its accumulated messages and throw the
635 * next time.
636 *
637 * It also saves the type of the exception to throw the next time.
638 */
639 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
ea003032
SM
640
641 struct LibErrorDeleter final
642 {
643 void operator()(const bt_error * const error) const noexcept
644 {
645 bt_error_release(error);
646 }
647 };
648
649 std::unique_ptr<const bt_error, LibErrorDeleter> _mSavedLibError;
212313d9
SM
650
651protected:
652 bt2c::Logger _mLogger;
653};
654
ee137c4e
PP
655namespace internal {
656
657template <typename UserComponentT, typename CompClsBridgeT, typename LibSpecCompClsPtrT,
658 typename AsCompClsFuncT, typename SetInitMethodFuncT, typename SetFinalizeMethodFuncT,
659 typename SetGetSupportedMipVersionsMethodFuncT, typename SetQueryMethodFuncT>
660void setCompClsCommonProps(
661 LibSpecCompClsPtrT * const libSpecCompClsPtr, AsCompClsFuncT&& asCompClsFunc,
662 SetInitMethodFuncT&& setInitMethodFunc, SetFinalizeMethodFuncT&& setFinalizeMethodFunc,
663 SetGetSupportedMipVersionsMethodFuncT&& setGetSupportedMipVersionsMethodFunc,
664 SetQueryMethodFuncT&& setQueryMethodFunc)
665{
666 const auto libCompClsPtr = asCompClsFunc(libSpecCompClsPtr);
667
668 if (UserComponentT::description != nullptr) {
669 const auto status =
670 bt_component_class_set_description(libCompClsPtr, UserComponentT::description);
671
672 if (status == BT_COMPONENT_CLASS_SET_DESCRIPTION_STATUS_MEMORY_ERROR) {
673 throw MemoryError {};
674 }
675 }
676
677 if (UserComponentT::help != nullptr) {
678 const auto status = bt_component_class_set_help(libCompClsPtr, UserComponentT::help);
679
680 if (status == BT_COMPONENT_CLASS_SET_HELP_STATUS_MEMORY_ERROR) {
681 throw MemoryError {};
682 }
683 }
684
685 {
686 const auto status = setInitMethodFunc(libSpecCompClsPtr, CompClsBridgeT::init);
687
688 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
689 }
690
691 {
692 const auto status = setFinalizeMethodFunc(libSpecCompClsPtr, CompClsBridgeT::finalize);
693
694 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
695 }
696
697 {
698 const auto status = setGetSupportedMipVersionsMethodFunc(
699 libSpecCompClsPtr, CompClsBridgeT::getSupportedMipVersions);
700
701 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
702 }
703
704 {
705 const auto status = setQueryMethodFunc(libSpecCompClsPtr, CompClsBridgeT::query);
706
707 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
708 }
709}
710
711template <typename MsgIterClsBridgeT>
712bt_message_iterator_class *createLibMsgIterCls()
713{
714 const auto libMsgIterClsPtr = bt_message_iterator_class_create(MsgIterClsBridgeT::next);
715
716 if (!libMsgIterClsPtr) {
717 throw MemoryError {};
718 }
719
720 {
721 const auto status = bt_message_iterator_class_set_initialize_method(
722 libMsgIterClsPtr, MsgIterClsBridgeT::init);
723
724 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
725 }
726
727 {
728 const auto status = bt_message_iterator_class_set_finalize_method(
729 libMsgIterClsPtr, MsgIterClsBridgeT::finalize);
730
731 BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK);
732 }
733
734 return libMsgIterClsPtr;
735}
736
737template <typename UserComponentT>
738bt_component_class_source *createSourceCompCls()
739{
740 static_assert(
741 std::is_base_of<UserSourceComponent<
742 UserComponentT, typename UserComponentT::MessageIterator,
743 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
744 UserComponentT>::value,
745 "`UserComponentT` inherits `UserSourceComponent`");
746
747 using CompClsBridge = internal::SrcCompClsBridge<UserComponentT>;
748 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
749
750 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
751 const auto libCompClsPtr =
752 bt_component_class_source_create(UserComponentT::name, libMsgIterClsPtr);
753
754 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
755
756 if (!libCompClsPtr) {
757 throw MemoryError {};
758 }
759
760 setCompClsCommonProps<UserComponentT, CompClsBridge>(
761 libCompClsPtr, bt_component_class_source_as_component_class,
762 bt_component_class_source_set_initialize_method,
763 bt_component_class_source_set_finalize_method,
764 bt_component_class_source_set_get_supported_mip_versions_method,
765 bt_component_class_source_set_query_method);
766
767 {
768 const auto status = bt_component_class_source_set_output_port_connected_method(
769 libCompClsPtr, CompClsBridge::outputPortConnected);
770
771 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
772 }
773
774 return libCompClsPtr;
775}
776
777template <typename UserComponentT>
778bt_component_class_filter *createFilterCompCls()
779{
780 static_assert(
781 std::is_base_of<UserFilterComponent<
782 UserComponentT, typename UserComponentT::MessageIterator,
783 typename UserComponentT::InitData, typename UserComponentT::QueryData>,
784 UserComponentT>::value,
785 "`UserComponentT` inherits `UserFilterComponent`");
786
787 using CompClsBridge = internal::FltCompClsBridge<UserComponentT>;
788 using MsgIterClsBridge = internal::MsgIterClsBridge<typename UserComponentT::MessageIterator>;
789
790 const auto libMsgIterClsPtr = createLibMsgIterCls<MsgIterClsBridge>();
791 const auto libCompClsPtr =
792 bt_component_class_filter_create(UserComponentT::name, libMsgIterClsPtr);
793
794 bt_message_iterator_class_put_ref(libMsgIterClsPtr);
795
796 if (!libCompClsPtr) {
797 throw MemoryError {};
798 }
799
800 setCompClsCommonProps<UserComponentT, CompClsBridge>(
801 libCompClsPtr, bt_component_class_filter_as_component_class,
802 bt_component_class_filter_set_initialize_method,
803 bt_component_class_filter_set_finalize_method,
804 bt_component_class_filter_set_get_supported_mip_versions_method,
805 bt_component_class_filter_set_query_method);
806
807 {
808 const auto status = bt_component_class_filter_set_input_port_connected_method(
809 libCompClsPtr, CompClsBridge::inputPortConnected);
810
811 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
812 }
813
814 {
815 const auto status = bt_component_class_filter_set_output_port_connected_method(
816 libCompClsPtr, CompClsBridge::outputPortConnected);
817
818 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
819 }
820
821 return libCompClsPtr;
822}
823
824template <typename UserComponentT>
825bt_component_class_sink *createSinkCompCls()
826{
827 static_assert(
828 std::is_base_of<UserSinkComponent<UserComponentT, typename UserComponentT::InitData,
829 typename UserComponentT::QueryData>,
830 UserComponentT>::value,
831 "`UserComponentT` inherits `UserSinkComponent`");
832
833 using CompClsBridge = internal::SinkCompClsBridge<UserComponentT>;
834
835 const auto libCompClsPtr =
836 bt_component_class_sink_create(UserComponentT::name, CompClsBridge::consume);
837
838 if (!libCompClsPtr) {
839 throw MemoryError {};
840 }
841
842 setCompClsCommonProps<UserComponentT, CompClsBridge>(
843 libCompClsPtr, bt_component_class_sink_as_component_class,
844 bt_component_class_sink_set_initialize_method, bt_component_class_sink_set_finalize_method,
845 bt_component_class_sink_set_get_supported_mip_versions_method,
846 bt_component_class_sink_set_query_method);
847
848 {
849 const auto status = bt_component_class_sink_set_graph_is_configured_method(
850 libCompClsPtr, CompClsBridge::graphIsConfigured);
851
852 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
853 }
854
855 {
856 const auto status = bt_component_class_sink_set_input_port_connected_method(
857 libCompClsPtr, CompClsBridge::inputPortConnected);
858
859 BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
860 }
861
862 return libCompClsPtr;
863}
864
865} /* namespace internal */
212313d9
SM
866} /* namespace bt2 */
867
868#endif /* BABELTRACE_CPP_COMMON_BT2_COMPONENT_CLASS_DEV_HPP */
This page took 0.05508 seconds and 4 git commands to generate.