Compute Graph Framework SDK Reference  5.16
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-2023 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 <utility>
45
46#include <fiu/fiu.hpp>
47#include <fiu/FaultRegistry.hpp>
48
49namespace dw
50{
51namespace framework
52{
53
55{
56public:
57 ManagedPortBase(const dw::core::StringView& name);
58
59 virtual ~ManagedPortBase() = default;
60
65 ManagedPortBase(const ManagedPortBase& other) = delete;
66 ManagedPortBase& operator=(const ManagedPortBase& other) = delete;
69
77 virtual void bindChannel(ChannelObject* channel) = 0;
78
85
89 virtual bool isBound() const noexcept = 0;
90
92 const dw::core::StringView& getName() const;
93
95 const dw::core::StringView& getNodeName() const;
96
98 virtual void setNodeName(const dw::core::StringView& nodeName) noexcept;
99
103 void setCycleCount(uint32_t cycleCount);
104
108 void setPeriod(uint32_t period);
109
114 virtual void reset();
115
121
122protected:
124 dw::core::StringView m_name;
126 dw::core::StringView m_nodeName;
127 uint32_t m_cycleCount;
128 uint32_t m_period;
130 dw::framework::lockstep::ILockstepSyncClient* m_lockstepSyncClient;
132};
133
138{
139public:
140 // Due to single TU checking
141 // coverity[autosar_cpp14_a0_1_1_violation]
142 static constexpr char LOG_TAG[]{"ManagedPortOutputBase"};
143
145 {
146 };
147
149 {
154 bool syncEnabled = false;
155 };
156
158 {
161 };
165 bool isBufferAvailable() const noexcept;
166
170 dw::core::VectorFixed<GenericData> getAllBuffers();
171
179 void acquire();
180
188 void send();
189
190 const Properties& getProperties() const noexcept;
191
195 void setCallbackBeforeSend(dw::core::Function<dwStatus()> callback);
196
197 // Implemented inherited methods
198 void bindChannel(ChannelObject* channel) override;
199 bool isBound() const noexcept override;
200
205 void reset() override;
206
211 ChannelMetadata& getMetadata();
212
216 void sendAdvTimestamp();
217
218 void setNodeName(const dw::core::StringView& nodeName) noexcept override;
219
220protected:
221 explicit ManagedPortOutputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref, std::type_index typeIndex);
222 GenericData getBufferGeneric();
223
224private:
225 static BoundProperties getBoundProperties(const ChannelObject& channel);
226 void populateDefaultMetadata(ChannelMetadata& header);
228 ChannelObject::Producer* m_channelProducer;
229 Properties m_props;
230 dw::core::Optional<GenericData> m_buffer;
231 dw::core::Function<dwStatus()> m_callbackBeforeSend;
232 uint32_t m_sendSeqNum;
233 std::type_index m_typeIndex;
234 bool m_isNvsci{false};
235};
236
241{
242public:
243 using RingBuffer = dw::core::RingBuffer<GenericData>;
244
246 {
250 uint32_t maxBuffers = 1U;
256 dwTime_t waitTime = 0;
257 };
258
260 {
270 bool enableReuse = false;
271
275 bool syncEnabled = false;
280 uint32_t dataOffset = 0U;
281 };
282
284 {
293 };
294
298 const Properties& getProperties() const noexcept;
299
309 void recv();
310
316 void release();
317
322 void reset() override;
323
327 bool isBufferAvailable() const noexcept;
328
332 dw::core::VectorFixed<GenericData> getAllBuffers();
333
334 // Implemented inherited methods
335 void bindChannel(ChannelObject* channel) override;
336 bool isBound() const noexcept override;
337
342 void setCallbackAfterRecv(dw::core::Function<dwStatus()> callback);
343
348 const ChannelMetadata& getMetadata();
349
353 void sendAdvTimestamp();
354
355protected:
356 ManagedPortInputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref);
357 GenericData getBufferGeneric() const;
358 GenericData popBufferGeneric();
359 void releaseToChannel(void* data);
360
361private:
362 static BoundProperties getBoundProperties(const ChannelObject& channel);
363 bool recvSingle(dwTime_t waitTime);
364 bool stashConsumed();
365 bool packetStashed(GenericData packet);
366 void handleReuseDrop();
367
368 void releaseSingle();
369 bool postProcessLockstepReplayData(GenericData packet);
370 dwTime_t getWaitTime();
371 bool recvData();
372 bool waitForData();
373 void handleWaitFailure(dwStatus status);
374 void handleCallbackAfterRecv();
375
376 Properties m_props;
378 ChannelObject::Consumer* m_channelConsumer;
379 bool m_shouldDropFirstBuffer;
380 dw::core::Function<dwStatus()> m_callbackAfterRecv;
381
382protected:
383 RingBuffer m_buffers;
384 GenericData m_stashedFuturePacket;
385 bool m_stashValid;
386};
387
391template <typename T>
393{
395 "Channel packet type not declared. Ensure channel packet type "
396 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
397 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
398
399 using SpecimenT = typename parameter_traits<T>::SpecimenT;
400
401public:
408 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
409 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props, SpecimenT& ref)
410 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(&ref), std::type_index(typeid(T)))
411 {
412 }
413
419 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
420 ManagedPortOutput(const dw::core::StringView& name, SpecimenT& ref)
421 : ManagedPortOutputBase(name, {}, make_specimen<T>(&ref), std::type_index(typeid(T)))
422 {
423 }
424
429 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
430 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props)
431 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(nullptr), std::type_index(typeid(T)))
432 {
433 }
434
438 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
439 ManagedPortOutput(const dw::core::StringView& name)
440 : ManagedPortOutputBase(name, {}, make_specimen<T>(nullptr), std::type_index(typeid(T)))
441 {
442 }
443
447 detail::vectorIterable<T> getAllBufferIter()
448 {
449 return detail::vectorIterable<T>(getAllBuffers());
450 }
451
458 {
459 return detail::getBufferTyped<T>(getBufferGeneric());
460 }
461};
462
466template <typename T>
468{
470 "Channel packet type not declared. Ensure channel packet type "
471 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
472 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
473 // coverity[autosar_cpp14_a0_1_6_violation]
474 using SpecimenT = typename parameter_traits<T>::SpecimenT;
475
476 struct PacketDeleter;
477
478public:
479 struct iterable;
480
485 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props)
486 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(nullptr))
487 {
488 }
489
490 ManagedPortInput(const dw::core::StringView& name)
491 : ManagedPortInputBase(name, {}, make_specimen<T>(nullptr))
492 {
493 }
494
495 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props, SpecimenT specimen)
496 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(&specimen))
497 {
498 }
499
503 detail::vectorIterable<T> getAllBufferIter()
504 {
505 return detail::vectorIterable<T>(getAllBuffers());
506 }
507
514 {
515 return iterable(*this);
516 }
517
523 auto getBuffer() -> T*
524 {
525 return detail::getBufferTyped<T>(getBufferGeneric());
526 }
527
534 {
535 if (isBufferAvailable())
536 {
537 const dw::core::Optional<dwValidityStatus> valid{getValidityStatus(getMetadata())};
538 // At the moment if validity is not set it counts as valid
539 // Once all the publishers set the validity signal it can be changed
540 const bool isValid{!valid.has_value() || (DW_VALIDITY_VALID == valid->validity)};
541 if (isValid)
542 {
543 return getBuffer();
544 }
545 }
546 return nullptr;
547 }
548
555 auto getOptionalBuffer() -> T*
556 {
557 return isBufferAvailable() ? getBuffer() : nullptr;
558 }
559
560 using UniquePacketPtr = std::unique_ptr<T, PacketDeleter>;
561
563 {
564 GenericData packet{popBufferGeneric()};
565 T* ptr{detail::getBufferTyped<T>(packet)};
566 void* releasePtr{packet.getPointer()};
567 return UniquePacketPtr(ptr, PacketDeleter{this, releasePtr});
568 }
569
570 struct iterable
571 {
573 : m_port(port)
574 {
575 }
576
578 // There are no specific requirements on the template type
579 // coverity[autosar_cpp14_a14_1_1_violation]
580 template <class TT>
581 class iterator : public ManagedPortInputBase::RingBuffer::iterator
582 {
583 using Base = ManagedPortInputBase::RingBuffer::iterator;
584
585 public:
586 // Same naming is used in dwshared, hence keeping the iterator name and its accessors for now
587 // coverity[cert_dcl51_cpp_violation]
588 iterator(Base&& base, ManagedPortInput<T>& port)
589 : Base(std::move(base))
590 , m_port(port)
591 {
592 }
593
594 const Base& baseFromThis() const
595 {
596 return *this;
597 }
598
599 auto operator*() const -> TT*
600 {
601 GenericData buffer{*baseFromThis()};
602 return detail::getBufferTyped<TT>(buffer);
603 }
604
605 private:
606 ManagedPortInput<T>& m_port;
607 };
608
609 // coverity[cert_dcl51_cpp_violation]
610 iterator<T> begin() { return iterator<T>(m_port.m_buffers.begin(), m_port); }
611
612 // coverity[cert_dcl51_cpp_violation]
613 iterator<T> end() { return iterator<T>(m_port.m_buffers.end(), m_port); }
614
615 // coverity[cert_dcl51_cpp_violation]
616 iterator<const T> begin() const { return iterator<const T>(m_port.m_buffers.begin(), m_port); }
617
618 // coverity[cert_dcl51_cpp_violation]
619 iterator<const T> end() const { return iterator<const T>(m_port.m_buffers.end(), m_port); }
620
621 private:
622 ManagedPortInput<T>& m_port;
623 };
624
625private:
626 struct PacketDeleter
627 {
628 void operator()(T* p)
629 {
630 static_cast<void>(p);
631 port->releaseToChannel(releasePtr);
632 }
633 ManagedPortInput* port;
634 void* releasePtr;
635 };
636};
637
638template <typename T>
640
641// Create a port type specimen for a given port index
642namespace detail
643{
644template <
645 typename NodeT,
646 PortDirection Direction,
647 uint64_t DescriptorIndex>
648struct IsOutputNonPOD : std::integral_constant<bool, Direction == PortDirection::OUTPUT && parameter_traits<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT>
649{
650 // 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.");
651 static_assert(DescriptorIndex < portDescriptorSize<NodeT, Direction>(), "Invalid PortIndex.");
652};
653
654template <
655 typename NodeT,
656 PortDirection Direction,
657 uint64_t DescriptorIndex>
658typename std::enable_if<
659 !IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
661 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
662 createPortSpecimenByStaticIndex()
663{
664 GenericDataReference ref{make_specimen<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>(nullptr)};
665 ref.packetTypeID = dw::core::safeAdd(static_cast<dw::framework::ChannelPacketTypeID>(DWFRAMEWORK_METADATA_PACKET_TYPE_ID_OFFSET), static_cast<uint32_t>(ref.packetTypeID)).value();
666 return ref;
667}
668
669template <
670 typename NodeT,
671 PortDirection Direction,
672 uint64_t DescriptorIndex>
673typename std::enable_if<
674 IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
676 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
677 createPortSpecimenByStaticIndex()
678{
679 throw ExceptionWithStatus(DW_NOT_SUPPORTED, "createPortSpecimenByStaticIndex: Non POD output port is not supported");
680}
681
682template <
683 typename NodeT,
684 PortDirection Direction,
685 uint64_t... Idx>
686typename std::enable_if<(sizeof...(Idx) > 1), GenericDataReference>::type
687 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
688 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
689{
690 constexpr size_t ArraySize{sizeof...(Idx)};
691 if (descriptorIndex < ArraySize)
692 {
693 // coverity[autosar_cpp14_a20_8_4_violation]
694 std::array<GenericDataReference, ArraySize> specimens{
695 (Idx == descriptorIndex ? createPortSpecimenByStaticIndex<NodeT, Direction, Idx>() : GenericDataReference{})...};
696 return specimens[descriptorIndex];
697 }
698 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
699}
700
701// Above createPortSpecimenImpl actually covers correctly for all sizeof...(Idx)
702// but AutoSAR complaining about dead code and unreachable code branch when sizeof...(Idx) == 1.
703// Thus split it into three different implementations.
704template <
705 typename NodeT,
706 PortDirection Direction,
707 uint64_t... Idx>
708typename std::enable_if<(sizeof...(Idx) == 1), GenericDataReference>::type
709 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
710 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
711{
712 constexpr size_t ArraySize{sizeof...(Idx)};
713 if (descriptorIndex < ArraySize)
714 {
715 return createPortSpecimenByStaticIndex<NodeT, Direction, 0>();
716 }
717 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
718}
719
720template <
721 typename NodeT,
722 PortDirection Direction,
723 uint64_t... Idx>
724typename std::enable_if<(sizeof...(Idx) == 0), GenericDataReference>::type
725 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
726 createPortSpecimenImpl(size_t, std::index_sequence<Idx...>)
727{
728 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
729}
730
731template <
732 typename NodeT,
733 PortDirection Direction>
734// coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
735GenericDataReference createPortSpecimen(size_t descriptorIndex)
736{
737 return detail::createPortSpecimenImpl<NodeT, Direction>(
739 std::make_index_sequence<portDescriptorSize<NodeT, Direction>()>{});
740}
741} // namespace detail
742
743} // namespace framework
744} // namespace dw
745
746#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)
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)
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:40
iterator< const T > begin() const
iterable(ManagedPortInput< T > &port)