Compute Graph Framework SDK Reference  5.22
ManagedPort.hpp
Go to the documentation of this file.
1
2//
3// Notice
4// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
5// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
6// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
7// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8//
9// NVIDIA CORPORATION & AFFILIATES assumes no responsibility for the consequences of use of such
10// information or for any infringement of patents or other rights of third parties that may
11// result from its use. No license is granted by implication or otherwise under any patent
12// or patent rights of NVIDIA CORPORATION & AFFILIATES. No third party distribution is allowed unless
13// expressly authorized by NVIDIA. Details are subject to change without notice.
14// This code supersedes and replaces all information previously supplied.
15// NVIDIA CORPORATION & AFFILIATES products are not authorized for use as critical
16// components in life support devices or systems without express written approval of
17// NVIDIA CORPORATION & AFFILIATES.
18//
19// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
20// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
21//
22// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
23// property and proprietary rights in and to this material, related
24// documentation and any modifications thereto. Any use, reproduction,
25// disclosure or distribution of this material and related documentation
26// without an express license agreement from NVIDIA CORPORATION or
27// its affiliates is strictly prohibited.
28//
30
31#ifndef DW_FRAMEWORK_MANAGEDPORT_HPP_
32#define DW_FRAMEWORK_MANAGEDPORT_HPP_
33
35#include <dwcgf/port/Port.hpp>
39#include <dwshared/dwfoundation/dw/core/language/Optional.hpp>
40#include <dwshared/dwfoundation/dw/core/container/RingBuffer.hpp>
41#include <dwshared/dwfoundation/dw/core/container/StringView.hpp>
42#include <dwshared/dwfoundation/dw/core/language/Function.hpp>
43#include <type_traits>
44#include <typeindex>
45#include <utility>
46
47#include <fiu/fiu.hpp>
48#include <fiu/FaultRegistry.hpp>
49
50namespace dw
51{
52namespace framework
53{
54
56{
57public:
58 ManagedPortBase(const dw::core::StringView& name);
59
60 virtual ~ManagedPortBase() = default;
61
66 ManagedPortBase(const ManagedPortBase& other) = delete;
67 ManagedPortBase& operator=(const ManagedPortBase& other) = delete;
70
78 virtual void bindChannel(ChannelObject* channel) = 0;
79
86
90 virtual bool isBound() const noexcept = 0;
91
93 const dw::core::StringView& getName() const;
94
96 const dw::core::StringView& getNodeName() const;
97
99 virtual void setNodeName(const dw::core::StringView& nodeName) noexcept;
100
104 void setCycleCount(uint32_t cycleCount);
105
109 void setPeriod(uint32_t period);
110
115 virtual void reset();
116
122
123protected:
125 dw::core::StringView m_name;
127 dw::core::StringView m_nodeName;
128 uint32_t m_cycleCount;
129 uint32_t m_period;
131 dw::framework::lockstep::ILockstepSyncClient* m_lockstepSyncClient;
133};
134
139{
140public:
141 // Due to single TU checking
142 // coverity[autosar_cpp14_a0_1_1_violation]
143 static constexpr char LOG_TAG[]{"ManagedPortOutputBase"};
144
146 {
147 };
148
150 {
155 bool syncEnabled = false;
156 };
157
159 {
162 };
166 bool isBufferAvailable() const noexcept;
167
171 dw::core::VectorFixed<GenericData> getAllBuffers();
172
180 void acquire();
181
190 void send(const dwTime_t* publishTimestamp = nullptr);
191
192 const Properties& getProperties() const noexcept;
193
197 void setCallbackBeforeSend(dw::core::Function<dwStatus()> callback);
198
199 // Implemented inherited methods
200 void bindChannel(ChannelObject* channel) override;
201 bool isBound() const noexcept override;
202
207 void reset() override;
208
213 ChannelMetadata& getMetadata();
214
218 void sendAdvTimestamp();
219
220 void setNodeName(const dw::core::StringView& nodeName) noexcept override;
221
222 ChannelObject::Producer* getChannelProducer()
223 {
224 return m_channelProducer;
225 }
226
227protected:
228 explicit ManagedPortOutputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref, std::type_index typeIndex);
230
231private:
232 static BoundProperties getBoundProperties(const ChannelObject& channel);
233 void preSend(ChannelMetadata& header, const dwTime_t* publishTimestamp);
234 void checkFiInstances(bool& sendMessage);
235 void checkFiInstanceInvalidateMessageHeaders();
236 void checkFiInstanceZeroSequenceNumber();
237 void checkFiInstanceDropMessages(bool& sendMessage);
238 dwStatus maybeSendMessage(bool sendMessage);
240 ChannelObject::Producer* m_channelProducer;
241 Properties m_props;
242 dw::core::Optional<GenericData> m_buffer;
243 dw::core::Function<dwStatus()> m_callbackBeforeSend;
244 uint32_t m_sendSeqNum;
245 std::type_index m_typeIndex;
246 bool m_isNvsci{false};
247};
248
253{
254public:
255 using RingBuffer = dw::core::RingBuffer<GenericData>;
256
258 {
262 uint32_t maxBuffers = 1U;
268 dwTime_t waitTime = 0;
269 };
270
272 {
282 bool enableReuse = false;
283
287 bool syncEnabled = false;
292 uint32_t dataOffset = 0U;
293 };
294
296 {
305 };
306
310 const Properties& getProperties() const noexcept;
311
321 void recv();
322
328 void release();
329
334 void reset() override;
335
339 bool isBufferAvailable() const noexcept;
340
344 dw::core::VectorFixed<GenericData> getAllBuffers();
345
346 // Implemented inherited methods
347 void bindChannel(ChannelObject* channel) override;
348 bool isBound() const noexcept override;
349
354 void setCallbackAfterRecv(dw::core::Function<dwStatus()> callback);
355
360 const ChannelMetadata& getMetadata();
361
365 void sendAdvTimestamp();
366
367protected:
368 ManagedPortInputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref);
369 GenericData getBufferGeneric() const;
370 GenericData popBufferGeneric();
371 void releaseToChannel(void* data);
372
373private:
374 static BoundProperties getBoundProperties(const ChannelObject& channel);
375 bool recvSingle(dwTime_t waitTime);
376 bool stashConsumed();
377 bool packetStashed(GenericData packet);
378 void handleReuseDrop();
379
380 void releaseSingle();
381 bool postProcessLockstepReplayData(GenericData packet);
382 dwTime_t getWaitTime();
383 bool recvData();
384 bool waitForData();
385 void handleWaitFailure(dwStatus status);
386 void handleCallbackAfterRecv();
387
388 Properties m_props;
390 ChannelObject::Consumer* m_channelConsumer;
391 bool m_shouldDropFirstBuffer;
392 dw::core::Function<dwStatus()> m_callbackAfterRecv;
393
394protected:
395 RingBuffer m_buffers;
396 GenericData m_stashedFuturePacket;
397 bool m_stashValid;
398};
399
403template <typename T>
405{
406 static_assert(std::is_constructible<T>::value, "T must be constructible");
408 "Channel packet type not declared. Ensure channel packet type "
409 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
410 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
411
412 using SpecimenT = typename parameter_traits<T>::SpecimenT;
413
414public:
421 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
422 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props, SpecimenT& ref)
423 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(&ref), std::type_index(typeid(T)))
424 {
425 }
426
432 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
433 ManagedPortOutput(const dw::core::StringView& name, SpecimenT& ref)
434 : ManagedPortOutput(name, {}, ref)
435 {
436 }
437
442 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
443 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props)
444 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(nullptr), std::type_index(typeid(T)))
445 {
446 }
447
451 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
452 ManagedPortOutput(const dw::core::StringView& name)
453 : ManagedPortOutput(name, {})
454 {
455 }
456
460 detail::vectorIterable<T> getAllBufferIter()
461 {
462 return detail::vectorIterable<T>(getAllBuffers());
463 }
464
471 {
472 return detail::getBufferTyped<T>(getBufferGeneric());
473 }
474};
475
479template <typename T>
481{
482 static_assert(std::is_constructible<T>::value, "T must be constructible");
484 "Channel packet type not declared. Ensure channel packet type "
485 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
486 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
487 // coverity[autosar_cpp14_a0_1_6_violation]
488 using SpecimenT = typename parameter_traits<T>::SpecimenT;
489
490 struct PacketDeleter;
491
492public:
493 struct iterable;
494
499 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props)
500 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(nullptr))
501 {
502 }
503
504 ManagedPortInput(const dw::core::StringView& name)
506 {
507 }
508
509 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props, SpecimenT specimen)
510 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(&specimen))
511 {
512 }
513
514 ManagedPortInput(const dw::core::StringView& name, SpecimenT specimen)
515 : ManagedPortInput(name, {}, specimen)
516 {
517 }
518
522 detail::vectorIterable<T> getAllBufferIter()
523 {
524 return detail::vectorIterable<T>(getAllBuffers());
525 }
526
533 {
534 return iterable(*this);
535 }
536
542 auto getBuffer() -> T*
543 {
544 return detail::getBufferTyped<T>(getBufferGeneric());
545 }
546
553 {
554 if (isBufferAvailable())
555 {
556 const dw::core::Optional<dwValidityStatus> valid{getValidityStatus(getMetadata())};
557 // At the moment if validity is not set it counts as valid
558 // Once all the publishers set the validity signal it can be changed
559 const bool isValid{!valid.has_value() || (DW_VALIDITY_VALID == valid->validity)};
560 if (isValid)
561 {
562 return getBuffer();
563 }
564 }
565 return nullptr;
566 }
567
574 auto getOptionalBuffer() -> T*
575 {
576 return isBufferAvailable() ? getBuffer() : nullptr;
577 }
578
579 using UniquePacketPtr = std::unique_ptr<T, PacketDeleter>;
580
582 {
583 GenericData packet{popBufferGeneric()};
584 T* ptr{detail::getBufferTyped<T>(packet)};
585 void* releasePtr{packet.getPointer()};
586 return UniquePacketPtr(ptr, PacketDeleter{this, releasePtr});
587 }
588
589 struct iterable
590 {
592 : m_port(port)
593 {
594 }
595
597 template <class TT>
598 class iterator : public ManagedPortInputBase::RingBuffer::iterator
599 {
600 static_assert(std::is_constructible<TT>::value, "TT must be constructible");
601
602 using Base = ManagedPortInputBase::RingBuffer::iterator;
603
604 public:
605 // Same naming is used in dwshared, hence keeping the iterator name and its accessors for now
606 iterator(Base&& base, ManagedPortInput<T>& port)
607 : Base(std::move(base))
608 , m_port(port)
609 {
610 }
611
612 const Base& baseFromThis() const
613 {
614 return *this;
615 }
616
617 auto operator*() const -> TT*
618 {
619 GenericData buffer{*baseFromThis()};
620 return detail::getBufferTyped<TT>(buffer);
621 }
622
623 private:
624 ManagedPortInput<T>& m_port;
625 };
626
627 iterator<T> begin() { return iterator<T>(m_port.m_buffers.begin(), m_port); }
628
629 iterator<T> end() { return iterator<T>(m_port.m_buffers.end(), m_port); }
630
631 iterator<const T> begin() const { return iterator<const T>(m_port.m_buffers.begin(), m_port); }
632
633 iterator<const T> end() const { return iterator<const T>(m_port.m_buffers.end(), m_port); }
634
635 private:
636 ManagedPortInput<T>& m_port;
637 };
638
639private:
640 struct PacketDeleter
641 {
642 void operator()(T* p)
643 {
644 static_cast<void>(p);
645 port->releaseToChannel(releasePtr);
646 }
647 ManagedPortInput* port;
648 void* releasePtr;
649 };
650};
651
652template <typename T>
654
655// Create a port type specimen for a given port index
656namespace detail
657{
658template <
659 typename NodeT,
660 PortDirection Direction,
661 uint64_t DescriptorIndex>
662struct IsOutputNonPOD : std::integral_constant<bool, Direction == PortDirection::OUTPUT && parameter_traits<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT>
663{
664 // static_assert(!std::is_pod<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>::value && parameter_traits<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>::IsDeclared, "The packet type is not yet declared.");
665 static_assert(DescriptorIndex < portDescriptorSize<NodeT, Direction>(), "Invalid PortIndex.");
666};
667
668template <
669 typename NodeT,
670 PortDirection Direction,
671 uint64_t DescriptorIndex>
672typename std::enable_if<
673 !IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
675 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
676 createPortSpecimenByStaticIndex()
677{
678 GenericDataReference ref{make_specimen<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>(nullptr)};
679 ref.packetTypeID = dw::core::safeAdd(static_cast<dw::framework::ChannelPacketTypeID>(DWFRAMEWORK_METADATA_PACKET_TYPE_ID_OFFSET), static_cast<uint32_t>(ref.packetTypeID)).value();
680 return ref;
681}
682
683template <
684 typename NodeT,
685 PortDirection Direction,
686 uint64_t DescriptorIndex>
687typename std::enable_if<
688 IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
690 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
691 createPortSpecimenByStaticIndex()
692{
693 throw ExceptionWithStatus(DW_NOT_SUPPORTED, "createPortSpecimenByStaticIndex: Non POD output port is not supported");
694}
695
696template <
697 typename NodeT,
698 PortDirection Direction,
699 uint64_t... Idx>
700typename std::enable_if<(sizeof...(Idx) > 1), GenericDataReference>::type
701 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
702 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
703{
704 constexpr size_t ArraySize{sizeof...(Idx)};
705 if (descriptorIndex < ArraySize)
706 {
707 // coverity[autosar_cpp14_a20_8_4_violation] FP: nvbugs/4552679
708 std::array<GenericDataReference, ArraySize> specimens{
709 (Idx == descriptorIndex ? createPortSpecimenByStaticIndex<NodeT, Direction, Idx>() : GenericDataReference{})...};
710 return specimens[descriptorIndex];
711 }
712 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
713}
714
715// Above createPortSpecimenImpl actually covers correctly for all sizeof...(Idx)
716// but AutoSAR complaining about dead code and unreachable code branch when sizeof...(Idx) == 1.
717// Thus split it into three different implementations.
718template <
719 typename NodeT,
720 PortDirection Direction,
721 uint64_t... Idx>
722typename std::enable_if<(sizeof...(Idx) == 1), GenericDataReference>::type
723 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
724 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
725{
726 constexpr size_t ArraySize{sizeof...(Idx)};
727 if (descriptorIndex < ArraySize)
728 {
729 return createPortSpecimenByStaticIndex<NodeT, Direction, 0>();
730 }
731 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
732}
733
734template <
735 typename NodeT,
736 PortDirection Direction,
737 uint64_t... Idx>
738typename std::enable_if<(sizeof...(Idx) == 0), GenericDataReference>::type
739 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
740 createPortSpecimenImpl(size_t, std::index_sequence<Idx...>)
741{
742 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
743}
744
745template <
746 typename NodeT,
747 PortDirection Direction>
748// coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
749GenericDataReference createPortSpecimen(size_t descriptorIndex)
750{
751 return detail::createPortSpecimenImpl<NodeT, Direction>(
753 std::make_index_sequence<portDescriptorSize<NodeT, Direction>()>{});
754}
755} // namespace detail
756
757} // namespace framework
758} // namespace dw
759
760#endif // DW_FRAMEWORK_MANAGEDPORT_HPP_
dw::core::StringView m_name
The unique name within set of ports with the same direction.
ManagedPortBase & operator=(ManagedPortBase &&other)=delete
virtual bool isBound() const noexcept=0
FI_DECLARE_INSTANCE_SET_HANDLE(m_fiHandle)
virtual ~ManagedPortBase()=default
const dw::core::StringView & getNodeName() const
Get the name of the node this port belongs to.
virtual void setNodeName(const dw::core::StringView &nodeName) noexcept
Set the name of the node this port belongs to.
ManagedPortBase(const ManagedPortBase &other)=delete
virtual void bindChannel(ChannelObject *channel)=0
ChannelObject * getChannel()
ManagedPortBase(ManagedPortBase &&other)=delete
ManagedPortBase & operator=(const ManagedPortBase &other)=delete
const dw::core::StringView & getName() const
Get the name of the port.
void bindLockstepSyncClient(dw::framework::lockstep::ILockstepSyncClient *syncClient)
dw::framework::lockstep::ILockstepSyncClient * m_lockstepSyncClient
ManagedPortBase(const dw::core::StringView &name)
dw::core::StringView m_nodeName
The name of the node this port belongs to.
void setCycleCount(uint32_t cycleCount)
void setPeriod(uint32_t period)
dw::core::RingBuffer< GenericData > RingBuffer
const Properties & getProperties() const noexcept
iterator(Base &&base, ManagedPortInput< T > &port)
detail::vectorIterable< T > getAllBufferIter()
ManagedPortInput(const dw::core::StringView &name, SpecimenT specimen)
ManagedPortInput(const dw::core::StringView &name)
std::unique_ptr< T, PacketDeleter > UniquePacketPtr
ManagedPortInput(const dw::core::StringView &name, ConstructProperties props, SpecimenT specimen)
auto getBufferIfAvailableAndValid() -> T *
ManagedPortInput(const dw::core::StringView &name, ConstructProperties props)
ManagedPortOutputBase(const dw::core::StringView &name, ConstructProperties props, GenericDataReference &&ref, std::type_index typeIndex)
bool isBufferAvailable() const noexcept
ManagedPortOutput(const dw::core::StringView &name, SpecimenT &ref)
ManagedPortOutput(const dw::core::StringView &name, ConstructProperties props)
ManagedPortOutput(const dw::core::StringView &name)
ManagedPortOutput(const dw::core::StringView &name, ConstructProperties props, SpecimenT &ref)
detail::vectorIterable< T > getAllBufferIter()
static constexpr const uint32_t DWFRAMEWORK_METADATA_PACKET_TYPE_ID_OFFSET
static GenericDataReference make_specimen(typename parameter_traits< T >::SpecimenT *specimen)
ChannelPacketTypeID packetTypeID
The ID of the type of the endpoint.
dw::core::Optional< dwValidityStatus > getValidityStatus(ChannelMetadata const &header)
uint32_t ChannelPacketTypeID
constexpr ChannelPacketTypeID DWFRAMEWORK_PACKET_ID_DEFAULT
typename ManagedPortInput< T >::UniquePacketPtr UniquePacketPtr
constexpr size_t descriptorIndex()
Definition: Buffer.hpp:41
iterator< const T > begin() const
iterable(ManagedPortInput< T > &port)