Compute Graph Framework SDK Reference  5.8
Port.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) 2018-2022 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_PORT_H_
32#define DW_FRAMEWORK_PORT_H_
33
35
36#include "SyncPortHelper.hpp"
37
38#include <stdexcept>
39#include <string>
40
41namespace dw
42{
43namespace framework
44{
45
47enum class PortDirection : uint8_t
48{
49 INPUT = 0,
50 OUTPUT,
51 COUNT,
52};
53
55{
56public:
57 virtual ~PortBase() = default;
58};
59
61class Port : public PortBase
62{
63public:
64 virtual dwStatus bindChannel(ChannelObject* channel) = 0;
65 virtual dwStatus initialize() { return DW_SUCCESS; }
66 virtual bool isBound() = 0;
67};
68
70
77template <typename T>
78class PortOutput : public SyncPortHelperOutput<T>, public Port
79{
80public:
82 using ApiDataTypeT = T;
85
86 static_assert(std::is_copy_constructible<SpecimenT>::value, "SpecimenT is not copy constructible");
87
88 static constexpr char LOG_TAG[] = "PortOutput";
89
90private:
91 ChannelObject::Producer* m_channelProducer{};
92 SpecimenT m_reference{};
93 OnSetSyncAttrs m_waiterAttrs{};
94 OnSetSyncAttrs m_signalerAttrs{};
95
96public:
97 explicit PortOutput(SpecimenT const& ref)
98 : m_reference(ref)
99 {
100 }
101 explicit PortOutput(SpecimenT&& ref)
102 : m_reference(std::move(ref))
103 {
104 }
105
106 explicit PortOutput(SpecimenT const& ref,
107 OnSetSyncAttrs signalerAttrs,
108 OnSetSyncAttrs waiterAttrs = {})
109 : m_reference(ref)
110 , m_waiterAttrs(waiterAttrs)
111 , m_signalerAttrs(signalerAttrs)
112 {
113 }
114
115 // Channel Bind
116 dwStatus bindChannel(ChannelObject* channel) override
117 {
118 auto ref = make_specimen<T>(&m_reference);
119 return bindChannelWithReference(channel, ref);
120 }
121
123 {
124 return Exception::guard([&] {
125 if (isBound())
126 {
127 // TODO(chale): this should be an Exception but applications are currently
128 // doing this. Those applications should be fixed.
129 FRWK_LOGE << "PortOutput: bindChannel: attempted to bind the same port twice, ignoring this bind!" << Logger::State::endl;
130 return;
131 }
132 if (channel == nullptr)
133 {
134 throw Exception(DW_INVALID_ARGUMENT, "PortOutput: bindChannel: expected channel != nullptr");
135 }
136
138
140 {
142 }
143
144 ref.setWaiterAttributes = m_waiterAttrs;
145 ref.setSignalerAttributes = m_signalerAttrs;
146
147 m_channelProducer = channel->getProducer(ref);
148 if (m_channelProducer == nullptr)
149 {
150 throw Exception(DW_INTERNAL_ERROR, "PortOutput bindChannel: wrong channel implementations returned.");
151 }
152 });
153 }
154
156 {
157 if (!isBound())
158 {
159 throw Exception(DW_NOT_AVAILABLE, "PortOutput: setOnDataReady: no bound channel");
160 }
161 m_channelProducer->setOnDataReady(opaque, onDataReady);
162 }
163
164 bool isBound() final
165 {
166 return (m_channelProducer != nullptr);
167 }
168
169 dwStatus wait(dwTime_t timeout)
170 {
171 if (!isBound())
172 {
173 throw Exception(DW_NOT_AVAILABLE, "PortInput: wait: no bound channel");
174 }
175
176 return m_channelProducer->wait(timeout);
177 }
178
179 // Node accessors
180 // TODO(unknown): This function's prototype needs to change to properly propagate errors
182 {
183 dwStatus status = DW_FAILURE;
184 GenericData genericData{};
185 if (m_channelProducer)
186 {
187 status = m_channelProducer->get(&genericData);
188 }
189
190 if (status != DW_SUCCESS)
191 {
192 return nullptr;
193 }
194
196 {
197 return BaseSyncHelper::extractInternalPacket(genericData);
198 }
199
200 return genericData.template getData<T>();
201 }
202
203 // Tx Operations
204 virtual dwStatus send(T* frame)
205 {
206 if (!m_channelProducer)
207 {
208 throw Exception(DW_NOT_AVAILABLE, "PortOutput: channel not bound");
209 }
210
212 {
213 return m_channelProducer->send(BaseSyncHelper::getSyncPacket(frame));
214 }
215
216 return m_channelProducer->send(frame);
217 }
218
220 {
221 if (!m_channelProducer)
222 {
223 throw Exception(DW_NOT_AVAILABLE, "PortOutput: channel not bound");
224 }
225 return m_channelProducer->getSyncSignaler();
226 }
227
228 void setSignalFences(T* frame, dw::core::span<NvSciSyncFence> fences)
229 {
231 {
232 m_channelProducer->getSyncSignaler().setSignalFences(BaseSyncHelper::getSyncPacket(frame), fences);
233 }
234 else
235 {
236 m_channelProducer->getSyncSignaler().setSignalFences(frame, fences);
237 }
238 }
239
241 {
242 if (!m_channelProducer)
243 {
244 throw Exception(DW_NOT_AVAILABLE, "PortOutput: channel not bound");
245 }
246 return m_channelProducer->getSyncWaiter();
247 }
248
249 void getWaitFences(T* frame, dw::core::span<NvSciSyncFence> fences)
250 {
252 {
253 m_channelProducer->getSyncWaiter().getWaitFences(BaseSyncHelper::getSyncPacket(frame), fences);
254 }
255 else
256 {
257 m_channelProducer->getSyncWaiter().getWaitFences(frame, fences);
258 }
259 }
260};
261
262template <typename T>
263constexpr char PortOutput<T>::LOG_TAG[];
264
266
273template <typename T>
274class PortInput : public SyncPortHelperInput<T>, public Port
275{
276 static constexpr char LOG_TAG[] = "PortInput";
277
278public:
280 using ApiDataTypeT = T;
283
284 static_assert(std::is_copy_constructible<SpecimenT>::value, "SpecimenT is not copy constructible");
285
286 explicit PortInput(SpecimenT const& ref)
287 : m_reference(ref)
288 {
289 }
290 explicit PortInput(SpecimenT&& ref)
291 : m_reference(std::move(ref))
292 {
293 }
294
296 {
297 }
298
299 explicit PortInput(OnSetSyncAttrs waiterAttrs,
300 OnSetSyncAttrs signalerAttrs = {})
301 : m_waiterAttrs(waiterAttrs)
302 , m_signalerAttrs(signalerAttrs)
303 {
304 }
305
306 explicit PortInput(SpecimenT const& ref,
307 OnSetSyncAttrs waiterAttrs,
308 OnSetSyncAttrs signalerAttrs = {})
309 : m_reference(ref)
310 , m_waiterAttrs(waiterAttrs)
311 , m_signalerAttrs(signalerAttrs)
312 {
313 }
314
315 ~PortInput() override = default;
316
317 // Channel Bind
318 dwStatus bindChannel(ChannelObject* channel) override
319 {
320 return Exception::guard([&] {
321 if (isBound())
322 {
323 // TODO(chale): this should be an Exception but applications are currently
324 // doing this. Those applications should be fixed.
325 FRWK_LOGE << "PortInput: bindChannel: attempted to bind the same port twice, ignoring this bind!" << Logger::State::endl;
326 return;
327 }
328 if (channel == nullptr)
329 {
330 throw Exception(DW_INVALID_ARGUMENT, "PortInput: bindChannel: expected channel != nullptr");
331 }
332
334 auto ref = make_specimen<T>(nullptr);
335
336 if (m_reference)
337 {
338 ref = make_specimen<T>(&m_reference.value());
339 }
340
342 {
343 ref.packetTypeID = BaseSyncHelper::getNewPacketID(ref.packetTypeID);
344 }
345
346 ref.setWaiterAttributes = m_waiterAttrs;
347 ref.setSignalerAttributes = m_signalerAttrs;
348
349 m_channelConsumer = channel->getConsumer(ref);
350 if (m_channelConsumer == nullptr)
351 {
352 throw Exception(DW_INTERNAL_ERROR, "PortInput bindChannel: wrong channel implementations returned.");
353 }
354 m_reuse = channel->getParams().getReuseEnabled();
355 });
356 }
357
358 bool isBound() override
359 {
360 return !(m_channelConsumer == nullptr);
361 }
362
364 {
365 if (!isBound())
366 {
367 throw Exception(DW_NOT_AVAILABLE, "PortInput: setOnDataReady: no bound channel");
368 }
369 m_channelConsumer->setOnDataReady(opaque, onDataReady);
370 }
371
372 // Rx Operations
373 dwStatus wait(dwTime_t timeout)
374 {
375 if (!isBound())
376 {
377 throw Exception(DW_NOT_AVAILABLE, "PortInput: wait: no bound channel");
378 }
379
380 // For synced packets, the wait can return DW_NOT_AVAILABLE or DW_SUCCESS
381 // if there are no packets to consume. This is because you need to consume
382 // a packet to make sure it's valid or not.
384 {
385 return DW_SUCCESS;
386 }
388 {
389 return DW_NOT_AVAILABLE;
390 }
392 {
393 timeout = 0;
394 }
395
396 dwTime_t waitTime = m_last ? 0 : timeout;
397 dwStatus status = m_channelConsumer->wait(waitTime);
398 if (m_last && (status == DW_TIME_OUT || status == DW_NOT_AVAILABLE))
399 {
400 return DW_SUCCESS;
401 }
402
403 return status;
404 }
405
406 // TODO(unknown): This function's prototype needs to change to properly propagate errors
407 virtual std::shared_ptr<T> recv()
408 {
410 std::shared_ptr<T> result;
411 if (!isBound())
412 {
413 return nullptr;
414 }
415
416 T* typedData = nullptr;
417 void* releasePtr = nullptr;
418
420 {
421 // There is a valid packet to consume
423 releasePtr = data.getPointer();
425 }
427 {
428 // There is a buffered packet, but it's not ready to be consumed.
429 return nullptr;
430 }
431 else
432 {
433 dwStatus status = m_channelConsumer->recv(&data);
434 if (status != DW_SUCCESS)
435 {
436 if (m_last != nullptr)
437 {
438 return m_last;
439 }
440 else
441 {
442 return nullptr;
443 }
444 }
445 releasePtr = data.getPointer();
446
448 {
450 if (!typedData)
451 {
452 return nullptr;
453 }
454 }
455 else
456 {
457 typedData = data.template getData<T>();
458 }
459 }
460
461 // don't rely on this class's member when releasing packet
462 auto* channelConsumer = m_channelConsumer;
463 result = std::shared_ptr<T>(typedData, [channelConsumer, releasePtr](T*) {
464 channelConsumer->release(releasePtr);
465 });
466 if (m_reuse)
467 {
468 m_last = result;
469 }
470
471 return result;
472 }
473
475 {
476 if (!m_channelConsumer)
477 {
478 throw Exception(DW_NOT_AVAILABLE, "PortInput: channel not bound");
479 }
480 return m_channelConsumer->getSyncSignaler();
481 }
482
483 void setSignalFences(T* frame, dw::core::span<NvSciSyncFence> fences)
484 {
486 {
487 throw Exception(DW_NOT_SUPPORTED, "PortInput: not supported");
488 }
489 else
490 {
491 m_channelConsumer->getSyncSignaler().setSignalFences(frame, fences);
492 }
493 }
494
496 {
497 if (!m_channelConsumer)
498 {
499 throw Exception(DW_NOT_AVAILABLE, "PortInput: channel not bound");
500 }
501 return m_channelConsumer->getSyncWaiter();
502 }
503
504 void getWaitFences(T* frame, dw::core::span<NvSciSyncFence> fences)
505 {
507 {
508 throw Exception(DW_NOT_SUPPORTED, "PortInput: not supported");
509 }
510 else
511 {
512 m_channelConsumer->getSyncWaiter().getWaitFences(frame, fences);
513 }
514 }
515
516private:
517 ChannelObject::Consumer* m_channelConsumer{};
518 bool m_reuse{};
519 std::shared_ptr<T> m_last{};
520 dw::core::Optional<SpecimenT> m_reference{};
521 OnSetSyncAttrs m_waiterAttrs{};
522 OnSetSyncAttrs m_signalerAttrs{};
523};
524
525template <typename T>
526constexpr char PortInput<T>::LOG_TAG[];
527
528} // namespace framework
529} // namespace dw
530
531#endif // DW_FRAMEWORK_PORT_H_
#define FRWK_LOGE
Definition: Logger.hpp:41
virtual dwStatus recv(GenericData *data)=0
virtual dwStatus wait(dwTime_t timeout)=0
virtual void setOnDataReady(void *opaque, OnDataReady onDataReady)=0
dw::core::Function< void()> OnDataReady
Definition: Channel.hpp:136
virtual dwStatus get(GenericData *data)=0
virtual dwStatus send(void *data)=0
virtual void setSignalFences(void *data, dw::core::span< const NvSciSyncFence > postFences)=0
virtual void getWaitFences(void *data, dw::core::span< NvSciSyncFence > &waitFences)=0
virtual Producer * getProducer(GenericDataReference ref)=0
virtual const ChannelParams & getParams() const =0
virtual Consumer * getConsumer(GenericDataReference ref)=0
static dwStatus guard(TryBlock tryBlock, dw::core::Logger::Verbosity verbosity=dw::core::Logger::Verbosity::DEBUG)
Definition: Exception.hpp:228
virtual ~PortBase()=default
PortInput(OnSetSyncAttrs waiterAttrs, OnSetSyncAttrs signalerAttrs={})
Definition: Port.hpp:299
virtual std::shared_ptr< T > recv()
Definition: Port.hpp:407
dwStatus wait(dwTime_t timeout)
Definition: Port.hpp:373
ChannelObject::SyncSignaler & getSyncSignaler()
Definition: Port.hpp:474
PortInput(SpecimenT const &ref, OnSetSyncAttrs waiterAttrs, OnSetSyncAttrs signalerAttrs={})
Definition: Port.hpp:306
dwStatus bindChannel(ChannelObject *channel) override
Definition: Port.hpp:318
ChannelObject::SyncWaiter & getSyncWaiter()
Definition: Port.hpp:495
typename parameter_traits< T >::SpecimenT SpecimenT
Definition: Port.hpp:281
void setSignalFences(T *frame, dw::core::span< NvSciSyncFence > fences)
Definition: Port.hpp:483
bool isBound() override
Definition: Port.hpp:358
static constexpr PortDirection DIRECTION
Definition: Port.hpp:279
void setOnDataReady(void *opaque, ChannelObject::PacketPool::OnDataReady onDataReady)
Definition: Port.hpp:363
~PortInput() override=default
void getWaitFences(T *frame, dw::core::span< NvSciSyncFence > fences)
Definition: Port.hpp:504
PortInput(SpecimenT &&ref)
Definition: Port.hpp:290
PortInput(SpecimenT const &ref)
Definition: Port.hpp:286
dwStatus wait(dwTime_t timeout)
Definition: Port.hpp:169
static constexpr char LOG_TAG[]
Definition: Port.hpp:88
dwStatus bindChannelWithReference(ChannelObject *channel, GenericDataReference &ref)
Definition: Port.hpp:122
dwStatus bindChannel(ChannelObject *channel) override
Definition: Port.hpp:116
void setOnDataReady(void *opaque, ChannelObject::PacketPool::OnDataReady onDataReady)
Definition: Port.hpp:155
PortOutput(SpecimenT const &ref)
Definition: Port.hpp:97
typename parameter_traits< T >::SpecimenT SpecimenT
Definition: Port.hpp:83
ChannelObject::SyncSignaler & getSyncSignaler()
Definition: Port.hpp:219
bool isBound() final
Definition: Port.hpp:164
PortOutput(SpecimenT const &ref, OnSetSyncAttrs signalerAttrs, OnSetSyncAttrs waiterAttrs={})
Definition: Port.hpp:106
void setSignalFences(T *frame, dw::core::span< NvSciSyncFence > fences)
Definition: Port.hpp:228
ChannelObject::SyncWaiter & getSyncWaiter()
Definition: Port.hpp:240
void getWaitFences(T *frame, dw::core::span< NvSciSyncFence > fences)
Definition: Port.hpp:249
static constexpr PortDirection DIRECTION
Definition: Port.hpp:81
PortOutput(SpecimenT &&ref)
Definition: Port.hpp:101
virtual dwStatus send(T *frame)
Definition: Port.hpp:204
virtual dwStatus bindChannel(ChannelObject *channel)=0
virtual bool isBound()=0
virtual dwStatus initialize()
Definition: Port.hpp:65
T * extractInternalPacket(GenericData genericData)
T * extractInternalPacket(GenericData genericData)
SyncedPacketPayload * getSyncPacket(T *frame)
void parseDataSynced(const ChannelParams &params) override
dw::core::Function< void(NvSciSyncAttrList)> OnSetSyncAttrs
dwCalibrationStatus status
Definition: Exception.hpp:47
ChannelPacketTypeID getNewPacketID(ChannelPacketTypeID packetTypeID)
virtual void parseDataSynced(const ChannelParams &params)