Holoscan SDK v4.2.0

Template Class HoloIpcCudaNativeBufferAdapterBase

Base Type

template<typename TransportType>
class HoloIpcCudaNativeBufferAdapterBase : public holoscan::NativeBufferProtocolAdapter

Shared CUDA IPC + holoipc lifecycle adapter core, parameterized on the holoipc transport.

Owns all transport-independent logic: GPU info caching, CudaTensorDescriptor conversion, CUDA IPC export/import via GXF helpers, holoipc share_pointer/acquire_pointer lifecycle, DNBX (Descriptor Native Buffer eXport) wire-format encode/decode, pending-export tracking, and deferred destruction.

Subclasses provide only the initialize() signature and ipc::Context<Transport> creation.

Threading: three threads access this object &#8212;

  • GXF scheduler (export_tensor, evict_stale_exports)

  • sidecar dispatch (import_tensor)

  • IpcCore io_context (handle_last_release callback) exports_mutex_ protects pending_exports_, lifecycle_key_to_seq_, released_entries_.

ExportEntry destruction must happen outside both exports_mutex_ and the io_context thread because the ipc_descriptor deleter takes IpcCore::mutex_ and may re-enter the io_context. The solution is deferred destruction: handle_last_release queues entries into released_entries_; the next export_tensor call drains them on the worker thread, freeing GPU memory inline and moving ipc_descriptors to a background thread.

Public Types

using IpcContextType = ipc::Context<TransportType>
using PointerDescriptorType = typename IpcContextType::PointerDescriptorType
using HandleType = typename IpcContextType::HandleType

Public Functions

inline explicit HoloIpcCudaNativeBufferAdapterBase(std::string adapter_name)
inline ~HoloIpcCudaNativeBufferAdapterBase() override
HoloIpcCudaNativeBufferAdapterBase(const HoloIpcCudaNativeBufferAdapterBase&) = delete
HoloIpcCudaNativeBufferAdapterBase &operator=(const HoloIpcCudaNativeBufferAdapterBase&) = delete
inline void shutdown()
inline virtual bool is_initialized() const override
inline nvidia::gxf::NativeBufferPolicy policy() const
inline void set_acquire_timeout(std::chrono::milliseconds timeout)
inline void set_export_ttl(std::chrono::milliseconds ttl)
inline void set_use_eager_acquire(bool enabled)
inline virtual const std::string &default_protocol_name() const override
inline virtual bool supports_protocol(const std::string &protocol_name) const override
inline virtual bool can_export_tensor(const nvidia::gxf::Tensor &tensor) const override
inline virtual uint8_t descriptor_format_version() const override
inline virtual nvidia::gxf::Expected<std::vector<uint8_t>> export_tensor(void *device_ptr, const std::shared_ptr<void> &device_ptr_owner, const NativeTensorMetadata &tensor_info, const std::string &protocol_name, uint32_t sequence_num) override

NativeBufferProtocolAdapter interface: converts NativeTensorMetadata to CudaTensorDescriptor and delegates to the CudaTensorDescriptor overload.

inline nvidia::gxf::Expected<std::vector<uint8_t>> export_tensor(void *device_ptr, const std::shared_ptr<void> &device_ptr_owner, const nvidia::gxf::CudaTensorDescriptor &tensor_info, const std::string &device_uuid, int32_t device_id, uint32_t sequence_num)

Export a GPU tensor for CUDA IPC transfer. Steps:

  1. Drain deferred-destroy entries from prior releases (see threading note above)

  2. Call gxf::export_cuda_ipc_descriptor() to get CudaIpcDescriptor + mem_handle

  3. Register with holoipc via share_pointer() using pre-exported handle bytes

  4. Encode into DNBX wire format (GXF descriptor + holoipc lifecycle metadata)

  5. Track in pending_exports_ for lifecycle management

inline virtual nvidia::gxf::Expected<ImportedNativeTensor> import_tensor_generic(const std::vector<uint8_t> &descriptor_bytes, const std::string &protocol_name, std::chrono::milliseconds timeout = std::chrono::milliseconds{0}) override

NativeBufferProtocolAdapter interface: delegates to import_tensor() and converts the NativeBufferHolder into a generic ImportedNativeTensor.

inline nvidia::gxf::Expected<NativeBufferHolder> import_tensor(const std::vector<uint8_t> &descriptor_bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds{0})

Decode a DNBX payload and acquire the CUDA IPC mapping via holoipc. In strict mode (default): sends ACQUIRED, waits for ACK, then opens handle. In eager mode: opens handle locally first, then sends ACQUIRED (no ACK wait). Returns an RAII NativeBufferHolder whose destruction sends RELEASED.

inline virtual size_t pending_export_count() const override
inline virtual void set_on_pending_export_count_changed(PendingExportCountChangedCallback callback) override
inline size_t evict_stale_exports(std::chrono::milliseconds max_age)

Public Static Functions

static inline nvidia::gxf::Expected<ExportedTensorDescriptor> decode_exported_tensor(const std::vector<uint8_t> &descriptor_bytes)

Parse DNBX wire format back into ExportedTensorDescriptor. Wire layout: magic | version | handle_type | ipc_version | hipc_blob | key | reply_topic

static inline nvidia::gxf::Expected<ExportedTensorDescriptor> decode_exported_tensor(const uint8_t *data, size_t size)

Protected Functions

inline nvidia::gxf::Expected<void> initialize_common(std::shared_ptr<IpcContextType> ipc_context, nvidia::gxf::NativeBufferPolicy policy)

Called by derived-class initialize() after creating the ipc::Context.

Protected Attributes

std::string adapter_name_

struct ExportedTensorDescriptor

Decoded DNBX payload: GXF CUDA IPC descriptor + holoipc lifecycle metadata.

Public Members

nvidia::gxf::CudaIpcDescriptor gxf_descriptor
std::vector<uint8_t> lifecycle_key
std::string lifecycle_reply_to_topic_name
int32_t handle_type = {0}
std::string ipc_protocol_version

struct NativeBufferHolder

RAII holder for a lifecycle-managed CUDA IPC mapping.

Public Functions

inline void *device_ptr() const
inline size_t byte_size() const

Public Members

nvidia::gxf::CudaIpcDescriptor descriptor
std::shared_ptr<void> ipc_device_ptr

Previous Template Class HoloEntitySerializerBase
Next Class HoloscanAsyncBufferReceiver
© Copyright 2022-2026, NVIDIA. Last updated on May 11, 2026