Commit | Line | Data |
---|---|---|
af38ae4f PP |
1 | /* |
2 | * Copyright (c) 2023 Simon Marchi <simon.marchi@efficios.com> | |
3 | * Copyright (c) 2023 Philippe Proulx <pproulx@efficios.com> | |
4 | * | |
5 | * SPDX-License-Identifier: MIT | |
6 | */ | |
7 | ||
8 | #ifndef BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP | |
9 | #define BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP | |
10 | ||
11 | #include <cstdint> | |
12 | ||
13 | #include <glib.h> | |
14 | ||
15 | #include <babeltrace2/babeltrace.h> | |
16 | ||
e7f0f07b | 17 | #include "cpp-common/bt2c/c-string-view.hpp" |
af38ae4f PP |
18 | #include "cpp-common/bt2c/logging.hpp" |
19 | #include "cpp-common/vendor/fmt/core.h" | |
20 | ||
21 | #include "exc.hpp" | |
22309699 | 22 | #include "internal/comp-cls-bridge.hpp" /* IWYU pragma: keep */ |
af38ae4f PP |
23 | |
24 | namespace bt2 { | |
af38ae4f PP |
25 | |
26 | template <typename UserMessageIteratorT, typename UserComponentT> | |
27 | class UserMessageIterator; | |
28 | ||
29 | /* | |
30 | * Base class of any user component. | |
31 | * | |
32 | * See the specific `bt2::UserSourceComponent`, | |
33 | * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`. | |
34 | */ | |
e76d65f0 | 35 | template <typename SelfCompT, typename InitDataT, typename QueryDataT> |
af38ae4f PP |
36 | class UserComponent |
37 | { | |
38 | /* Give a related message iterator access to this logger */ | |
39 | template <typename, typename> | |
40 | friend class UserMessageIterator; | |
41 | ||
e66071f3 SM |
42 | public: |
43 | using InitData = InitDataT; | |
e76d65f0 | 44 | using QueryData = QueryDataT; |
e66071f3 | 45 | |
af38ae4f PP |
46 | protected: |
47 | explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) : | |
48 | _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp} | |
49 | { | |
50 | } | |
51 | ||
52 | protected: | |
e7f0f07b | 53 | bt2c::CStringView _name() const noexcept |
af38ae4f PP |
54 | { |
55 | return _mSelfComp.name(); | |
56 | } | |
57 | ||
58 | LoggingLevel _loggingLevel() const noexcept | |
59 | { | |
60 | return _mSelfComp.loggingLevel(); | |
61 | } | |
62 | ||
63 | std::uint64_t _graphMipVersion() const noexcept | |
64 | { | |
65 | return _mSelfComp.graphMipVersion(); | |
66 | } | |
67 | ||
68 | SelfCompT _selfComp() noexcept | |
69 | { | |
70 | return _mSelfComp; | |
71 | } | |
72 | ||
73 | bt2c::Logger _mLogger; | |
74 | ||
75 | private: | |
76 | SelfCompT _mSelfComp; | |
77 | }; | |
78 | ||
79 | /* | |
80 | * Base class of a user source component `UserComponentT` (CRTP). | |
81 | * | |
e66071f3 SM |
82 | * UserComponentT::UserComponentT() must accept, in this order: |
83 | * | |
84 | * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward | |
85 | * to bt2::UserSourceComponent::UserSourceComponent(). | |
86 | * | |
87 | * 2. A `bt2::ConstValue` parameter (the initialization parameters). | |
88 | * | |
89 | * 3. An `InitDataT *` parameter (the initialization method data). | |
06bb401e SM |
90 | * |
91 | * `UserMessageIteratorT`, the message iterator class to use, must inherit | |
92 | * `UserMessageIterator`. | |
e76d65f0 SM |
93 | * |
94 | * UserComponentT::_query() receives a query method data pointer of type | |
95 | * `QueryDataT *` as its last parameter. | |
af38ae4f | 96 | */ |
e76d65f0 SM |
97 | template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void, |
98 | typename QueryDataT = void> | |
99 | class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT, QueryDataT> | |
af38ae4f | 100 | { |
06bb401e SM |
101 | static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>, |
102 | UserMessageIteratorT>::value, | |
103 | "`UserMessageIteratorT` inherits `UserMessageIterator`"); | |
104 | ||
105 | public: | |
106 | using MessageIterator = UserMessageIteratorT; | |
107 | ||
af38ae4f PP |
108 | protected: |
109 | using _OutputPorts = SelfSourceComponent::OutputPorts; | |
110 | ||
111 | explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) : | |
e76d65f0 | 112 | UserComponent<SelfSourceComponent, InitDataT, QueryDataT> {selfComp, logTag} |
af38ae4f PP |
113 | { |
114 | } | |
115 | ||
116 | public: | |
117 | static Value::Shared query(const SelfComponentClass selfCompCls, | |
15030982 | 118 | const PrivateQueryExecutor privQueryExec, |
e76d65f0 SM |
119 | const bt2c::CStringView obj, const ConstValue params, |
120 | QueryDataT * const data) | |
af38ae4f | 121 | { |
e76d65f0 | 122 | return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data); |
af38ae4f PP |
123 | } |
124 | ||
125 | static void getSupportedMipVersions(const SelfComponentClass selfCompCls, | |
126 | const ConstValue params, const LoggingLevel loggingLevel, | |
127 | const UnsignedIntegerRangeSet ranges) | |
128 | { | |
129 | UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges); | |
130 | } | |
131 | ||
132 | void outputPortConnected(const SelfComponentOutputPort outputPort, | |
133 | const ConstInputPort inputPort) | |
134 | { | |
830cf5dd | 135 | static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort); |
af38ae4f PP |
136 | } |
137 | ||
138 | protected: | |
139 | /* Overloadable */ | |
15030982 | 140 | static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView, |
e76d65f0 | 141 | ConstValue, QueryDataT *) |
af38ae4f PP |
142 | { |
143 | throw UnknownObject {}; | |
144 | } | |
145 | ||
146 | /* Overloadable */ | |
147 | static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel, | |
148 | const UnsignedIntegerRangeSet ranges) | |
149 | { | |
150 | ranges.addRange(0, 0); | |
151 | } | |
152 | ||
153 | /* Overloadable */ | |
154 | void _outputPortConnected(SelfComponentOutputPort, ConstInputPort) | |
155 | { | |
156 | } | |
157 | ||
158 | template <typename DataT> | |
830cf5dd | 159 | _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data) |
af38ae4f PP |
160 | { |
161 | return this->_selfComp().addOutputPort(name, data); | |
162 | } | |
163 | ||
15030982 | 164 | _OutputPorts::Port _addOutputPort(const bt2c::CStringView name) |
af38ae4f PP |
165 | { |
166 | return this->_selfComp().addOutputPort(name); | |
167 | } | |
168 | ||
169 | _OutputPorts _outputPorts() noexcept | |
170 | { | |
171 | return this->_selfComp().outputPorts(); | |
172 | } | |
173 | }; | |
174 | ||
175 | /* | |
176 | * Base class of a user filter component `UserComponentT` (CRTP). | |
177 | * | |
e66071f3 SM |
178 | * UserComponentT::UserComponentT() must accept, in this order: |
179 | * | |
180 | * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward | |
181 | * to bt2::UserFilterComponent::UserFilterComponent(). | |
182 | * | |
183 | * 2. A `bt2::ConstValue` parameter (the initialization parameters). | |
184 | * | |
185 | * 3. An `InitDataT *` parameter (the initialization method data). | |
06bb401e SM |
186 | * |
187 | * `UserMessageIteratorT`, the message iterator class to use, must inherit | |
188 | * `UserMessageIterator`. | |
e76d65f0 SM |
189 | * |
190 | * UserComponentT::_query() receives a query method data pointer of type | |
191 | * `QueryDataT *` as its last parameter. | |
af38ae4f | 192 | */ |
e76d65f0 SM |
193 | template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void, |
194 | typename QueryDataT = void> | |
195 | class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT, QueryDataT> | |
af38ae4f | 196 | { |
06bb401e SM |
197 | static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>, |
198 | UserMessageIteratorT>::value, | |
199 | "`UserMessageIteratorT` inherits `UserMessageIterator`"); | |
200 | ||
201 | public: | |
202 | using MessageIterator = UserMessageIteratorT; | |
203 | ||
af38ae4f PP |
204 | protected: |
205 | using _InputPorts = SelfFilterComponent::InputPorts; | |
206 | using _OutputPorts = SelfFilterComponent::OutputPorts; | |
207 | ||
208 | explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) : | |
e76d65f0 | 209 | UserComponent<SelfFilterComponent, InitDataT, QueryDataT> {selfComp, logTag} |
af38ae4f PP |
210 | { |
211 | } | |
212 | ||
213 | public: | |
214 | static Value::Shared query(const SelfComponentClass selfCompCls, | |
15030982 | 215 | const PrivateQueryExecutor privQueryExec, |
e76d65f0 SM |
216 | const bt2c::CStringView obj, const ConstValue params, |
217 | QueryDataT * const data) | |
af38ae4f | 218 | { |
e76d65f0 | 219 | return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data); |
af38ae4f PP |
220 | } |
221 | ||
222 | static void getSupportedMipVersions(const SelfComponentClass selfCompCls, | |
223 | const ConstValue params, const LoggingLevel loggingLevel, | |
224 | const UnsignedIntegerRangeSet ranges) | |
225 | { | |
226 | UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges); | |
227 | } | |
228 | ||
229 | void inputPortConnected(const SelfComponentInputPort inputPort, | |
230 | const ConstOutputPort outputPort) | |
231 | { | |
232 | static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort); | |
233 | } | |
234 | ||
235 | void outputPortConnected(const SelfComponentOutputPort outputPort, | |
236 | const ConstInputPort inputPort) | |
237 | { | |
238 | static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort); | |
239 | } | |
240 | ||
241 | protected: | |
242 | /* Overloadable */ | |
15030982 | 243 | static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView, |
e76d65f0 | 244 | ConstValue, QueryDataT *) |
af38ae4f PP |
245 | { |
246 | throw UnknownObject {}; | |
247 | } | |
248 | ||
249 | /* Overloadable */ | |
250 | static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel, | |
251 | const UnsignedIntegerRangeSet ranges) | |
252 | { | |
253 | ranges.addRange(0, 0); | |
254 | } | |
255 | ||
256 | /* Overloadable */ | |
257 | void _inputPortConnected(SelfComponentInputPort, ConstOutputPort) | |
258 | { | |
259 | } | |
260 | ||
261 | /* Overloadable */ | |
262 | void _outputPortConnected(SelfComponentOutputPort, ConstInputPort) | |
263 | { | |
264 | } | |
265 | ||
266 | template <typename DataT> | |
830cf5dd | 267 | _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data) |
af38ae4f PP |
268 | { |
269 | return this->_selfComp().addInputPort(name, data); | |
270 | } | |
271 | ||
15030982 | 272 | _InputPorts::Port _addInputPort(const bt2c::CStringView name) |
af38ae4f PP |
273 | { |
274 | return this->_selfComp().addInputPort(name); | |
275 | } | |
276 | ||
277 | _InputPorts _inputPorts() noexcept | |
278 | { | |
279 | return this->_selfComp().inputPorts(); | |
280 | } | |
281 | ||
282 | template <typename DataT> | |
830cf5dd | 283 | _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT& data) |
af38ae4f PP |
284 | { |
285 | return this->_selfComp().addOutputPort(name, data); | |
286 | } | |
287 | ||
15030982 | 288 | _OutputPorts::Port _addOutputPort(const bt2c::CStringView name) |
af38ae4f PP |
289 | { |
290 | return this->_selfComp().addOutputPort(name); | |
291 | } | |
292 | ||
293 | _OutputPorts _outputPorts() noexcept | |
294 | { | |
295 | return this->_selfComp().outputPorts(); | |
296 | } | |
297 | }; | |
298 | ||
299 | /* | |
300 | * Base class of a user sink component `UserComponentT` (CRTP). | |
301 | * | |
e66071f3 SM |
302 | * UserComponentT::UserComponentT() must accept, in this order: |
303 | * | |
304 | * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward | |
305 | * to bt2::UserSinkComponent::UserSinkComponent(). | |
306 | * | |
307 | * 2. A `bt2::ConstValue` parameter (the initialization parameters). | |
308 | * | |
309 | * 3. An `InitDataT *` parameter (the initialization method data). | |
af38ae4f PP |
310 | * |
311 | * `UserComponentT` must implement: | |
312 | * | |
313 | * bool _consume(); | |
314 | * | |
315 | * This method returns `true` if the sink component still needs to | |
316 | * consume, or `false` if it's finished. | |
e76d65f0 SM |
317 | * |
318 | * UserComponentT::_query() receives a query method data pointer of type | |
319 | * `QueryDataT *` as its last parameter. | |
320 | ||
af38ae4f | 321 | */ |
e76d65f0 SM |
322 | template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void> |
323 | class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT> | |
af38ae4f PP |
324 | { |
325 | protected: | |
326 | using _InputPorts = SelfSinkComponent::InputPorts; | |
327 | ||
328 | explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) : | |
e76d65f0 | 329 | UserComponent<SelfSinkComponent, InitDataT, QueryDataT> {selfComp, logTag} |
af38ae4f PP |
330 | { |
331 | } | |
332 | ||
333 | public: | |
334 | static Value::Shared query(const SelfComponentClass selfCompCls, | |
15030982 | 335 | const PrivateQueryExecutor privQueryExec, |
e76d65f0 SM |
336 | const bt2c::CStringView obj, const ConstValue params, |
337 | QueryDataT * const data) | |
af38ae4f | 338 | { |
e76d65f0 | 339 | return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data); |
af38ae4f PP |
340 | } |
341 | ||
342 | static void getSupportedMipVersions(const SelfComponentClass selfCompCls, | |
343 | const ConstValue params, const LoggingLevel loggingLevel, | |
344 | const UnsignedIntegerRangeSet ranges) | |
345 | { | |
346 | UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges); | |
347 | } | |
348 | ||
349 | void graphIsConfigured() | |
350 | { | |
351 | static_cast<UserComponentT&>(*this)._graphIsConfigured(); | |
352 | } | |
353 | ||
354 | void inputPortConnected(const SelfComponentInputPort inputPort, | |
355 | const ConstOutputPort outputPort) | |
356 | { | |
357 | static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort); | |
358 | } | |
359 | ||
360 | bool consume() | |
361 | { | |
362 | return static_cast<UserComponentT&>(*this)._consume(); | |
363 | } | |
364 | ||
365 | protected: | |
366 | /* Overloadable */ | |
15030982 | 367 | static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView, |
e76d65f0 | 368 | ConstValue, QueryDataT *) |
af38ae4f PP |
369 | { |
370 | throw UnknownObject {}; | |
371 | } | |
372 | ||
373 | /* Overloadable */ | |
374 | static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel, | |
375 | const UnsignedIntegerRangeSet ranges) | |
376 | { | |
377 | ranges.addRange(0, 0); | |
378 | } | |
379 | ||
380 | /* Overloadable */ | |
381 | void _graphIsConfigured() | |
382 | { | |
383 | } | |
384 | ||
385 | /* Overloadable */ | |
386 | void _inputPortConnected(SelfComponentInputPort, ConstOutputPort) | |
387 | { | |
388 | } | |
389 | ||
390 | MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port) | |
391 | { | |
392 | return this->_selfComp().createMessageIterator(port); | |
393 | } | |
394 | ||
395 | template <typename DataT> | |
830cf5dd | 396 | _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT& data) |
af38ae4f PP |
397 | { |
398 | return this->_selfComp().addInputPort(name, data); | |
399 | } | |
400 | ||
15030982 | 401 | _InputPorts::Port _addInputPort(const bt2c::CStringView name) |
af38ae4f PP |
402 | { |
403 | return this->_selfComp().addInputPort(name); | |
404 | } | |
405 | ||
406 | _InputPorts _inputPorts() noexcept | |
407 | { | |
408 | return this->_selfComp().inputPorts(); | |
409 | } | |
410 | }; | |
411 | ||
412 | /* | |
413 | * Base class of a user message iterator `UserMessageIteratorT` (CRTP) | |
414 | * of which the parent user component class is `UserComponentT`. | |
415 | * | |
416 | * `UserMessageIteratorT::UserMessageIteratorT()` must accept a | |
417 | * `bt2::SelfMessageIterator` parameter, which it needs to forward to | |
418 | * bt2::UserMessageIterator::UserMessageIterator(). | |
419 | * | |
420 | * The public next() method below (called by the bridge) implements the | |
421 | * very common pattern of appending messages into the output array, and, | |
422 | * meanwhile: | |
423 | * | |
424 | * If it catches a `bt2::TryAgain` exception: | |
425 | * If the message array isn't empty, transform this into a success | |
426 | * (don't throw). | |
427 | * | |
428 | * Otherwise rethrow. | |
429 | * | |
430 | * If it catches an error: | |
431 | * If the message array isn't empty, transform this into a success | |
432 | * (don't throw), but save the error of the current thread and the | |
433 | * type of error to throw the next time the user calls next(). | |
434 | * | |
435 | * Otherwise rethrow. | |
436 | * | |
437 | * `UserMessageIteratorT` must implement: | |
438 | * | |
439 | * void _next(bt2::ConstMessageArray& messages); | |
440 | * | |
441 | * This method fills `messages` with at most `messages.capacity()` | |
442 | * messages and may throw `bt2::TryAgain` or a valid error whenever. | |
443 | * Leaving an empty `messages` means the end of iteration. | |
444 | */ | |
445 | template <typename UserMessageIteratorT, typename UserComponentT> | |
446 | class UserMessageIterator | |
447 | { | |
448 | private: | |
449 | /* Type of `_mExcToThrowType` */ | |
450 | enum class _ExcToThrowType | |
451 | { | |
452 | NONE, | |
453 | ERROR, | |
454 | MEM_ERROR, | |
455 | }; | |
456 | ||
457 | protected: | |
458 | explicit UserMessageIterator(const SelfMessageIterator selfMsgIter, | |
459 | const std::string& logTagSuffix) : | |
460 | _mSelfMsgIter {selfMsgIter}, | |
461 | _mLogger {selfMsgIter, | |
462 | fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)} | |
463 | { | |
464 | } | |
465 | ||
466 | public: | |
467 | ~UserMessageIterator() | |
468 | { | |
469 | this->_resetError(); | |
470 | } | |
471 | ||
472 | void next(bt2::ConstMessageArray& messages) | |
473 | { | |
474 | /* Any saved error? Now is the time to throw */ | |
475 | if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) { | |
476 | /* Move `_mSavedLibError`, if any, as current thread error */ | |
477 | if (_mSavedLibError) { | |
478 | BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError); | |
479 | } | |
480 | ||
481 | /* Throw the corresponding exception */ | |
482 | if (_mExcToThrowType == _ExcToThrowType::ERROR) { | |
483 | throw bt2::Error {}; | |
484 | } else { | |
485 | BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR); | |
486 | throw bt2::MemoryError {}; | |
487 | } | |
488 | } | |
489 | ||
490 | /* | |
491 | * When catching some exception below, if our message array | |
492 | * isn't empty, then return immediately before throwing to | |
493 | * provide those messages to downstream. | |
494 | * | |
495 | * When catching an error, also save the current thread error, | |
496 | * if any, so that we can restore it later (see the beginning of | |
497 | * this method). | |
498 | */ | |
499 | BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE); | |
500 | ||
501 | try { | |
502 | this->_userObj()._next(messages); | |
503 | ||
504 | /* We're done: everything below is exception handling */ | |
505 | return; | |
506 | } catch (const bt2::TryAgain&) { | |
507 | if (messages.isEmpty()) { | |
508 | throw; | |
509 | } | |
510 | } catch (const std::bad_alloc&) { | |
511 | if (messages.isEmpty()) { | |
512 | throw; | |
513 | } | |
514 | ||
515 | _mExcToThrowType = _ExcToThrowType::MEM_ERROR; | |
516 | } catch (const bt2::Error&) { | |
517 | if (messages.isEmpty()) { | |
518 | throw; | |
519 | } | |
520 | ||
521 | _mExcToThrowType = _ExcToThrowType::ERROR; | |
522 | } | |
523 | ||
524 | if (_mExcToThrowType != _ExcToThrowType::NONE) { | |
525 | BT_CPPLOGE( | |
526 | "An error occurred, but there are {} messages to return: delaying the error reporting.", | |
527 | messages.length()); | |
528 | BT_ASSERT(!_mSavedLibError); | |
529 | _mSavedLibError = bt_current_thread_take_error(); | |
530 | } | |
531 | } | |
532 | ||
533 | bool canSeekBeginning() | |
534 | { | |
535 | this->_resetError(); | |
536 | return this->_userObj()._canSeekBeginning(); | |
537 | } | |
538 | ||
539 | void seekBeginning() | |
540 | { | |
541 | this->_resetError(); | |
542 | return this->_userObj()._seekBeginning(); | |
543 | } | |
544 | ||
545 | bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin) | |
546 | { | |
547 | this->_resetError(); | |
548 | return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin); | |
549 | } | |
550 | ||
551 | void seekNsFromOrigin(const std::int64_t nsFromOrigin) | |
552 | { | |
553 | this->_resetError(); | |
554 | this->_userObj()._seekNsFromOrigin(nsFromOrigin); | |
555 | } | |
556 | ||
557 | protected: | |
558 | /* Overloadable */ | |
559 | bool _canSeekBeginning() noexcept | |
560 | { | |
561 | return false; | |
562 | } | |
563 | ||
564 | /* Overloadable */ | |
565 | void _seekBeginning() noexcept | |
566 | { | |
567 | } | |
568 | ||
569 | /* Overloadable */ | |
570 | bool _canSeekNsFromOrigin(std::int64_t) noexcept | |
571 | { | |
572 | return false; | |
573 | } | |
574 | ||
575 | /* Overloadable */ | |
576 | void _seekNsFromOrigin(std::int64_t) noexcept | |
577 | { | |
578 | } | |
579 | ||
580 | MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port) | |
581 | { | |
582 | return _mSelfMsgIter.createMessageIterator(port); | |
583 | } | |
584 | ||
585 | UserComponentT& _component() noexcept | |
586 | { | |
587 | return _mSelfMsgIter.component().template data<UserComponentT>(); | |
588 | } | |
589 | ||
590 | SelfComponentOutputPort _port() noexcept | |
591 | { | |
592 | return _mSelfMsgIter.port(); | |
593 | } | |
594 | ||
595 | bool _isInterrupted() const noexcept | |
596 | { | |
597 | return _mSelfMsgIter.isInterrupted(); | |
598 | } | |
599 | ||
600 | private: | |
601 | UserMessageIteratorT& _userObj() noexcept | |
602 | { | |
603 | return static_cast<UserMessageIteratorT&>(*this); | |
604 | } | |
605 | ||
606 | void _resetError() noexcept | |
607 | { | |
608 | _mExcToThrowType = _ExcToThrowType::NONE; | |
609 | ||
610 | if (_mSavedLibError) { | |
611 | bt_error_release(_mSavedLibError); | |
612 | } | |
613 | } | |
614 | ||
615 | SelfMessageIterator _mSelfMsgIter; | |
616 | ||
617 | /* | |
618 | * next() may accumulate messages, and then catch an error before | |
619 | * returning. In that case, it saves the error of the current thread | |
620 | * here so that it can return its accumulated messages and throw the | |
621 | * next time. | |
622 | * | |
623 | * It also saves the type of the exception to throw the next time. | |
624 | */ | |
625 | _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE; | |
626 | const bt_error *_mSavedLibError = nullptr; | |
627 | ||
628 | protected: | |
629 | bt2c::Logger _mLogger; | |
630 | }; | |
631 | ||
632 | } /* namespace bt2 */ | |
633 | ||
06bb401e SM |
634 | #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \ |
635 | _userComponentClass) \ | |
af38ae4f PP |
636 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \ |
637 | _pluginId, _componentClassId, _name, \ | |
06bb401e | 638 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \ |
af38ae4f PP |
639 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \ |
640 | _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \ | |
641 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \ | |
642 | _pluginId, _componentClassId, \ | |
643 | bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \ | |
644 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \ | |
645 | _pluginId, _componentClassId, \ | |
646 | bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \ | |
647 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \ | |
648 | _pluginId, _componentClassId, \ | |
649 | bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \ | |
650 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \ | |
651 | _pluginId, _componentClassId, \ | |
652 | bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \ | |
653 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \ | |
654 | _pluginId, _componentClassId, \ | |
06bb401e | 655 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \ |
af38ae4f PP |
656 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \ |
657 | _pluginId, _componentClassId, \ | |
06bb401e | 658 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \ |
af38ae4f PP |
659 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \ |
660 | _pluginId, _componentClassId, \ | |
06bb401e SM |
661 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \ |
662 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \ | |
af38ae4f PP |
663 | BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \ |
664 | _pluginId, _componentClassId, \ | |
06bb401e SM |
665 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \ |
666 | bt2::internal::MsgIterClsBridge< \ | |
667 | _userComponentClass::MessageIterator>::canSeekNsFromOrigin); | |
af38ae4f | 668 | |
06bb401e SM |
669 | #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \ |
670 | _userComponentClass) \ | |
af38ae4f PP |
671 | BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \ |
672 | _pluginId, _componentClassId, _name, \ | |
06bb401e | 673 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \ |
af38ae4f PP |
674 | BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \ |
675 | _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \ | |
676 | BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \ | |
677 | _pluginId, _componentClassId, \ | |
678 | bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \ | |
679 | BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \ | |
680 | _pluginId, _componentClassId, \ | |
681 | bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \ | |
682 | BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \ | |
683 | _pluginId, _componentClassId, \ | |
684 | bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \ | |
685 | BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \ | |
686 | _pluginId, _componentClassId, \ | |
687 | bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \ | |
688 | BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \ | |
689 | _pluginId, _componentClassId, \ | |
690 | bt2::internal::FltCompClsBridge<_userComponentClass>::query); \ | |
691 | BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \ | |
692 | _pluginId, _componentClassId, \ | |
06bb401e | 693 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \ |
af38ae4f PP |
694 | BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \ |
695 | _pluginId, _componentClassId, \ | |
06bb401e | 696 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \ |
af38ae4f PP |
697 | BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \ |
698 | _pluginId, _componentClassId, \ | |
06bb401e SM |
699 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \ |
700 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \ | |
af38ae4f PP |
701 | BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \ |
702 | _pluginId, _componentClassId, \ | |
06bb401e SM |
703 | bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \ |
704 | bt2::internal::MsgIterClsBridge< \ | |
705 | _userComponentClass::MessageIterator>::canSeekNsFromOrigin); | |
af38ae4f PP |
706 | |
707 | #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \ | |
708 | _userComponentClass) \ | |
709 | BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \ | |
710 | _pluginId, _componentClassId, _name, \ | |
711 | bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \ | |
712 | BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \ | |
713 | _pluginId, _componentClassId, \ | |
714 | bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \ | |
715 | BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \ | |
716 | _pluginId, _componentClassId, \ | |
717 | bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \ | |
718 | BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \ | |
719 | _pluginId, _componentClassId, \ | |
720 | bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \ | |
721 | BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \ | |
722 | _pluginId, _componentClassId, \ | |
723 | bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \ | |
724 | BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \ | |
725 | _pluginId, _componentClassId, \ | |
726 | bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \ | |
727 | BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \ | |
728 | _pluginId, _componentClassId, \ | |
729 | bt2::internal::SinkCompClsBridge<_userComponentClass>::query); | |
730 | ||
06bb401e SM |
731 | #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass) \ |
732 | BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass) | |
af38ae4f | 733 | |
06bb401e SM |
734 | #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass) \ |
735 | BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass) | |
af38ae4f PP |
736 | |
737 | #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \ | |
738 | BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass) | |
739 | ||
740 | #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */ |