• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • Compute Graph Framework SDK Reference  5.14
    All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
    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
    46namespace dw
    47{
    48namespace framework
    49{
    50
    52{
    53public:
    54 ManagedPortBase(const dw::core::StringView& name);
    55
    56 virtual ~ManagedPortBase() = default;
    57
    62 ManagedPortBase(const ManagedPortBase& other) = delete;
    63 ManagedPortBase& operator=(const ManagedPortBase& other) = delete;
    66
    74 virtual void bindChannel(ChannelObject* channel) = 0;
    75
    82
    86 virtual bool isBound() const noexcept = 0;
    87
    89 const dw::core::StringView& getName() const;
    90
    92 const dw::core::StringView& getNodeName() const;
    93
    95 void setNodeName(const dw::core::StringView& nodeName) noexcept;
    96
    100 void setCycleCount(uint32_t cycleCount);
    101
    105 void setPeriod(uint32_t period);
    106
    111 virtual void reset();
    112
    118
    119protected:
    121 dw::core::StringView m_name;
    123 dw::core::StringView m_nodeName;
    124 uint32_t m_cycleCount;
    125 uint32_t m_period;
    127 dw::framework::lockstep::ILockstepSyncClient* m_lockstepSyncClient;
    128};
    129
    134{
    135public:
    136 // Due to single TU checking
    137 // coverity[autosar_cpp14_a0_1_1_violation]
    138 static constexpr char LOG_TAG[]{"ManagedPortOutputBase"};
    139
    141 {
    142 };
    143
    145 {
    150 bool syncEnabled = false;
    151 };
    152
    154 {
    157 };
    161 bool isBufferAvailable() const noexcept;
    162
    166 dw::core::VectorFixed<GenericData> getAllBuffers();
    167
    175 void acquire();
    176
    184 void send();
    185
    186 const Properties& getProperties() const noexcept;
    187
    191 void setCallbackBeforeSend(dw::core::Function<dwStatus()> callback);
    192
    193 // Implemented inherited methods
    194 void bindChannel(ChannelObject* channel) override;
    195 bool isBound() const noexcept override;
    196
    201 void reset() override;
    202
    207 ChannelMetadata& getMetadata();
    208
    212 void sendAdvTimestamp();
    213
    214protected:
    215 explicit ManagedPortOutputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref);
    216 GenericData getBufferGeneric();
    217
    218private:
    219 static BoundProperties getBoundProperties(const ChannelObject& channel);
    220 void populateDefaultMetadata(ChannelMetadata& header);
    222 ChannelObject::Producer* m_channelProducer;
    223 Properties m_props;
    224 dw::core::Optional<GenericData> m_buffer;
    225 dw::core::Function<dwStatus()> m_callbackBeforeSend;
    226 uint32_t m_sendSeqNum;
    227};
    228
    233{
    234public:
    235 using RingBuffer = dw::core::RingBuffer<GenericData>;
    236
    238 {
    242 uint32_t maxBuffers = 1U;
    248 dwTime_t waitTime = 0;
    249 };
    250
    252 {
    262 bool enableReuse = false;
    263
    267 bool syncEnabled = false;
    272 uint32_t dataOffset = 0U;
    273 };
    274
    276 {
    285 };
    286
    290 const Properties& getProperties() const noexcept;
    291
    301 void recv();
    302
    308 void release();
    309
    314 void reset() override;
    315
    319 bool isBufferAvailable() const noexcept;
    320
    324 dw::core::VectorFixed<GenericData> getAllBuffers();
    325
    326 // Implemented inherited methods
    327 void bindChannel(ChannelObject* channel) override;
    328 bool isBound() const noexcept override;
    329
    334 void setCallbackAfterRecv(dw::core::Function<dwStatus()> callback);
    335
    340 const ChannelMetadata& getMetadata();
    341
    345 void sendAdvTimestamp();
    346
    347protected:
    348 ManagedPortInputBase(const dw::core::StringView& name, ConstructProperties props, GenericDataReference&& ref);
    349 GenericData getBufferGeneric() const;
    350 GenericData popBufferGeneric();
    351 void releaseToChannel(void* data);
    352
    353private:
    354 static BoundProperties getBoundProperties(const ChannelObject& channel);
    355 bool recvSingle(dwTime_t waitTime);
    356 bool stashConsumed();
    357 bool packetStashed(GenericData packet);
    358 void handleReuseDrop();
    359
    360 void releaseSingle();
    361 bool postProcessLockstepReplayData(GenericData packet);
    362 dwTime_t getWaitTime();
    363 bool recvData();
    364 bool waitForData();
    365 void handleWaitFailure(dwStatus status);
    366 void handleCallbackAfterRecv();
    367
    368 Properties m_props;
    370 ChannelObject::Consumer* m_channelConsumer;
    371 bool m_shouldDropFirstBuffer;
    372 dw::core::Function<dwStatus()> m_callbackAfterRecv;
    373
    374protected:
    375 RingBuffer m_buffers;
    376 GenericData m_stashedFuturePacket;
    377 bool m_stashValid;
    378};
    379
    380namespace detail
    381{
    382
    383template <typename T>
    384// coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
    385T* getBufferTyped(GenericData buffer)
    386{
    387 MetadataPayload* metadataPacket{extractMetadata(buffer)};
    388 T* ptr{metadataPacket->data.template getData<T>()};
    389
    390 if (ptr == nullptr)
    391 {
    392 throw ExceptionWithStatus(DW_INVALID_ARGUMENT, "getBufferTyped: type mismatch");
    393 }
    394 return ptr;
    395}
    396
    397// coverity[autosar_cpp14_a14_1_1_violation]
    398template <typename T>
    399struct vectorIterable
    400{
    401 explicit vectorIterable(dw::core::VectorFixed<GenericData> allBuffers)
    402 : m_allBuffers(std::move(allBuffers))
    403 {
    404 }
    405
    407 // There are no specific requirements on the template type
    408 // coverity[autosar_cpp14_a14_1_1_violation]
    409 template <class TT>
    410 class iterator : public dw::core::VectorFixed<GenericData>::iterator
    411 {
    412 public:
    413 using Base = dw::core::VectorFixed<GenericData>::iterator;
    414 // Same naming is used in dwshared, hence keeping the iterator name and its accessors for now
    415 // coverity[cert_dcl51_cpp_violation]
    416 iterator(Base&& base)
    417 : Base(base)
    418 {
    419 }
    420
    421 const Base& baseFromThis() const
    422 {
    423 return *this;
    424 }
    425
    426 auto operator*() const
    427 {
    428 GenericData buffer = *baseFromThis();
    429 return getBufferTyped<TT>(buffer);
    430 }
    431 };
    432
    433 // coverity[cert_dcl51_cpp_violation]
    434 iterator<T> begin() { return iterator<T>(m_allBuffers.begin()); }
    435
    436 // coverity[cert_dcl51_cpp_violation]
    437 iterator<T> end() { return iterator<T>(m_allBuffers.end()); }
    438
    439 // coverity[cert_dcl51_cpp_violation]
    440 iterator<const T> begin() const { return iterator<const T>(m_allBuffers.begin()); }
    441
    442 // coverity[cert_dcl51_cpp_violation]
    443 iterator<const T> end() const { return iterator<const T>(m_allBuffers.end()); }
    444
    445private:
    446 dw::core::VectorFixed<GenericData> m_allBuffers;
    447};
    448
    449} // namespace detail
    450
    454template <typename T>
    456{
    458 "Channel packet type not declared. Ensure channel packet type "
    459 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
    460 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
    461
    462 using SpecimenT = typename parameter_traits<T>::SpecimenT;
    463
    464public:
    471 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
    472 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props, SpecimenT& ref)
    473 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(&ref))
    474 {
    475 }
    476
    482 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
    483 ManagedPortOutput(const dw::core::StringView& name, SpecimenT& ref)
    484 : ManagedPortOutputBase(name, {}, make_specimen<T>(&ref))
    485 {
    486 }
    487
    492 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
    493 ManagedPortOutput(const dw::core::StringView& name, ConstructProperties props)
    494 : ManagedPortOutputBase(name, std::move(props), make_specimen<T>(nullptr))
    495 {
    496 }
    497
    501 template <typename T2 = T, typename std::enable_if_t<parameter_traits<T2>::PacketTID == DWFRAMEWORK_PACKET_ID_DEFAULT, void>* = nullptr>
    502 ManagedPortOutput(const dw::core::StringView& name)
    503 : ManagedPortOutputBase(name, {}, make_specimen<T>(nullptr))
    504 {
    505 }
    506
    510 // coverity[autosar_cpp14_a7_1_5_violation]
    512 {
    513 return detail::vectorIterable<T>(getAllBuffers());
    514 }
    515
    521 auto getBuffer() -> T*
    522 {
    523 return detail::getBufferTyped<T>(getBufferGeneric());
    524 }
    525};
    526
    530template <typename T>
    532{
    534 "Channel packet type not declared. Ensure channel packet type "
    535 "handling is declared with DWFRAMEWORK_DECLARE_PACKET_TYPE_POD "
    536 "or DWFRAMEWORK_DECLARE_PACKET_TYPE_RELATION");
    537 // coverity[autosar_cpp14_a0_1_6_violation]
    538 using SpecimenT = typename parameter_traits<T>::SpecimenT;
    539
    540 struct PacketDeleter;
    541
    542public:
    543 struct iterable;
    544
    549 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props)
    550 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(nullptr))
    551 {
    552 }
    553
    554 ManagedPortInput(const dw::core::StringView& name)
    555 : ManagedPortInputBase(name, {}, make_specimen<T>(nullptr))
    556 {
    557 }
    558
    559 ManagedPortInput(const dw::core::StringView& name, ConstructProperties props, SpecimenT specimen)
    560 : ManagedPortInputBase(name, std::move(props), make_specimen<T>(&specimen))
    561 {
    562 }
    563
    567 detail::vectorIterable<T> getAllBufferIter()
    568 {
    569 return detail::vectorIterable<T>(getAllBuffers());
    570 }
    571
    578 {
    579 return iterable(*this);
    580 }
    581
    587 auto getBuffer() -> T*
    588 {
    589 return detail::getBufferTyped<T>(getBufferGeneric());
    590 }
    591
    598 {
    599 if (isBufferAvailable())
    600 {
    601 const dw::core::Optional<dwValidityStatus> valid{getValidityStatus(getMetadata())};
    602 // At the moment if validity is not set it counts as valid
    603 // Once all the publishers set the validity signal it can be changed
    604 const bool isValid{!valid.has_value() || (valid->validity == DW_VALIDITY_VALID)};
    605 if (isValid)
    606 {
    607 return getBuffer();
    608 }
    609 }
    610 return nullptr;
    611 }
    612
    619 auto getOptionalBuffer() -> T*
    620 {
    621 return isBufferAvailable() ? getBuffer() : nullptr;
    622 }
    623
    624 using UniquePacketPtr = std::unique_ptr<T, PacketDeleter>;
    625
    627 {
    628 GenericData packet{popBufferGeneric()};
    629 T* ptr{detail::getBufferTyped<T>(packet)};
    630 void* releasePtr{packet.getPointer()};
    631 return UniquePacketPtr(ptr, PacketDeleter{this, releasePtr});
    632 }
    633
    634 struct iterable
    635 {
    637 : m_port(port)
    638 {
    639 }
    640
    642 // There are no specific requirements on the template type
    643 // coverity[autosar_cpp14_a14_1_1_violation]
    644 template <class TT>
    645 class iterator : public ManagedPortInputBase::RingBuffer::iterator
    646 {
    647 using Base = ManagedPortInputBase::RingBuffer::iterator;
    648
    649 public:
    650 // Same naming is used in dwshared, hence keeping the iterator name and its accessors for now
    651 // coverity[cert_dcl51_cpp_violation]
    652 iterator(Base&& base, ManagedPortInput<T>& port)
    653 : Base(std::move(base))
    654 , m_port(port)
    655 {
    656 }
    657
    658 const Base& baseFromThis() const
    659 {
    660 return *this;
    661 }
    662
    663 auto operator*() const -> TT*
    664 {
    665 GenericData buffer{*baseFromThis()};
    666 return detail::getBufferTyped<TT>(buffer);
    667 }
    668
    669 private:
    670 ManagedPortInput<T>& m_port;
    671 };
    672
    673 // coverity[cert_dcl51_cpp_violation]
    674 iterator<T> begin() { return iterator<T>(m_port.m_buffers.begin(), m_port); }
    675
    676 // coverity[cert_dcl51_cpp_violation]
    677 iterator<T> end() { return iterator<T>(m_port.m_buffers.end(), m_port); }
    678
    679 // coverity[cert_dcl51_cpp_violation]
    680 iterator<const T> begin() const { return iterator<const T>(m_port.m_buffers.begin(), m_port); }
    681
    682 // coverity[cert_dcl51_cpp_violation]
    683 iterator<const T> end() const { return iterator<const T>(m_port.m_buffers.end(), m_port); }
    684
    685 private:
    686 ManagedPortInput<T>& m_port;
    687 };
    688
    689private:
    690 struct PacketDeleter
    691 {
    692 void operator()(T* p)
    693 {
    694 static_cast<void>(p);
    695 port->releaseToChannel(releasePtr);
    696 }
    697 ManagedPortInput* port;
    698 void* releasePtr;
    699 };
    700};
    701
    702template <typename T>
    704
    705// Create a port type specimen for a given port index
    706namespace detail
    707{
    708template <
    709 typename NodeT,
    710 PortDirection Direction,
    711 uint64_t DescriptorIndex>
    712struct IsOutputNonPOD : std::integral_constant<bool, Direction == PortDirection::OUTPUT && parameter_traits<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>::PacketTID != DWFRAMEWORK_PACKET_ID_DEFAULT>
    713{
    714 static_assert(DescriptorIndex < portDescriptorSize<NodeT, Direction>(), "Invalid PortIndex.");
    715};
    716
    717template <
    718 typename NodeT,
    719 PortDirection Direction,
    720 uint64_t DescriptorIndex>
    721typename std::enable_if<
    722 !IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
    724 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
    725 createPortSpecimenByStaticIndex()
    726{
    727 GenericDataReference ref{make_specimen<decltype(portDescriptorType<NodeT, Direction, DescriptorIndex>())>(nullptr)};
    728 ref.packetTypeID = dw::core::safeAdd(static_cast<dw::framework::ChannelPacketTypeID>(DWFRAMEWORK_METADATA_PACKET_TYPE_ID_OFFSET), static_cast<uint32_t>(ref.packetTypeID)).value();
    729 return ref;
    730}
    731
    732template <
    733 typename NodeT,
    734 PortDirection Direction,
    735 uint64_t DescriptorIndex>
    736typename std::enable_if<
    737 IsOutputNonPOD<NodeT, Direction, DescriptorIndex>::value,
    739 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/3907242
    740 createPortSpecimenByStaticIndex()
    741{
    742 throw ExceptionWithStatus(DW_NOT_SUPPORTED, "createPortSpecimenByStaticIndex: Non POD output port is not supported");
    743}
    744
    745template <
    746 typename NodeT,
    747 PortDirection Direction,
    748 uint64_t... Idx>
    749typename std::enable_if<(sizeof...(Idx) > 1), GenericDataReference>::type
    750 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
    751 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
    752{
    753 constexpr size_t ArraySize{sizeof...(Idx)};
    754 if (descriptorIndex < ArraySize)
    755 {
    756 std::array<GenericDataReference, ArraySize> specimens{
    757 (Idx == descriptorIndex ? createPortSpecimenByStaticIndex<NodeT, Direction, Idx>() : GenericDataReference{})...};
    758 return specimens[descriptorIndex];
    759 }
    760 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
    761}
    762
    763// Above createPortSpecimenImpl actually covers correctly for all sizeof...(Idx)
    764// but AutoSAR complaining about dead code and unreachable code branch when sizeof...(Idx) == 1.
    765// Thus split it into three different implementations.
    766template <
    767 typename NodeT,
    768 PortDirection Direction,
    769 uint64_t... Idx>
    770typename std::enable_if<(sizeof...(Idx) == 1), GenericDataReference>::type
    771 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
    772 createPortSpecimenImpl(size_t descriptorIndex, std::index_sequence<Idx...>)
    773{
    774 constexpr size_t ArraySize{sizeof...(Idx)};
    775 if (descriptorIndex < ArraySize)
    776 {
    777 return createPortSpecimenByStaticIndex<NodeT, Direction, 0>();
    778 }
    779 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
    780}
    781
    782template <
    783 typename NodeT,
    784 PortDirection Direction,
    785 uint64_t... Idx>
    786typename std::enable_if<(sizeof...(Idx) == 0), GenericDataReference>::type
    787 // coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
    788 createPortSpecimenImpl(size_t, std::index_sequence<Idx...>)
    789{
    790 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS, "createPortSpecimenImpl: index out of bound.");
    791}
    792
    793template <
    794 typename NodeT,
    795 PortDirection Direction>
    796// coverity[autosar_cpp14_a2_10_5_violation] FP: nvbugs/4040101
    797GenericDataReference createPortSpecimen(size_t descriptorIndex)
    798{
    799 return detail::createPortSpecimenImpl<NodeT, Direction>(
    801 std::make_index_sequence<portDescriptorSize<NodeT, Direction>()>{});
    802}
    803} // namespace detail
    804
    805} // namespace framework
    806} // namespace dw
    807
    808#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
    void setNodeName(const dw::core::StringView &nodeName) noexcept
    Set the name of the node this port belongs to.
    virtual ~ManagedPortBase()=default
    const dw::core::StringView & getNodeName() const
    Get 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)
    static constexpr const uint32_t DWFRAMEWORK_METADATA_PACKET_TYPE_ID_OFFSET
    static GenericDataReference make_specimen(typename parameter_traits< T >::SpecimenT *specimen)
    MetadataPayload * extractMetadata(GenericData packet)
    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)
    人人超碰97caoporen国产