# This file was generated by stubgen-pyx v0.2.6 from cuda_core/cuda/core/_device.pyx

from __future__ import annotations

import threading

import cuda.core.system
from cuda.core._context import Context, ContextOptions
from cuda.core._device_resources import DeviceResources
from cuda.core._event import Event, EventOptions
from cuda.core._memory._buffer import Buffer, MemoryResource
from cuda.core._stream import IsStreamType, Stream
from cuda.core._utils.cuda_utils import ComputeCapability
from cuda.core.graph import GraphBuilder
from cuda.core.texture import (MipmappedArray, MipmappedArrayOptions,
                               OpaqueArray, OpaqueArrayOptions,
                               ResourceDescriptor, SurfaceObject,
                               TextureObject, TextureObjectOptions)


class DeviceProperties:
    """
    A class to query various attributes of a CUDA device.

    Attributes are read-only and provide information about the device.
    """

    def __init__(self, *args, **kwargs) -> None:
        ...

    @classmethod
    def _init(cls, handle: int) -> DeviceProperties:
        ...

    @property
    def max_threads_per_block(self) -> int:
        """int: Maximum number of threads per block."""

    @property
    def max_block_dim_x(self) -> int:
        """int: Maximum block dimension X."""

    @property
    def max_block_dim_y(self) -> int:
        """int: Maximum block dimension Y."""

    @property
    def max_block_dim_z(self) -> int:
        """int: Maximum block dimension Z."""

    @property
    def max_grid_dim_x(self) -> int:
        """int: Maximum grid dimension X."""

    @property
    def max_grid_dim_y(self) -> int:
        """int: Maximum grid dimension Y."""

    @property
    def max_grid_dim_z(self) -> int:
        """int: Maximum grid dimension Z."""

    @property
    def max_shared_memory_per_block(self) -> int:
        """int: Maximum shared memory available per block in bytes."""

    @property
    def total_constant_memory(self) -> int:
        """int: Memory available on device for constant variables in a CUDA C kernel in bytes."""

    @property
    def warp_size(self) -> int:
        """int: Warp size in threads."""

    @property
    def max_pitch(self) -> int:
        """int: Maximum pitch in bytes allowed by memory copies."""

    @property
    def maximum_texture1d_width(self) -> int:
        """int: Maximum 1D texture width."""

    @property
    def maximum_texture1d_linear_width(self) -> int:
        """int: Maximum width for a 1D texture bound to linear memory."""

    @property
    def maximum_texture1d_mipmapped_width(self) -> int:
        """int: Maximum mipmapped 1D texture width."""

    @property
    def maximum_texture2d_width(self) -> int:
        """int: Maximum 2D texture width."""

    @property
    def maximum_texture2d_height(self) -> int:
        """int: Maximum 2D texture height."""

    @property
    def maximum_texture2d_linear_width(self) -> int:
        """int: Maximum width for a 2D texture bound to linear memory."""

    @property
    def maximum_texture2d_linear_height(self) -> int:
        """int: Maximum height for a 2D texture bound to linear memory."""

    @property
    def maximum_texture2d_linear_pitch(self) -> int:
        """int: Maximum pitch in bytes for a 2D texture bound to linear memory."""

    @property
    def maximum_texture2d_mipmapped_width(self) -> int:
        """int: Maximum mipmapped 2D texture width."""

    @property
    def maximum_texture2d_mipmapped_height(self) -> int:
        """int: Maximum mipmapped 2D texture height."""

    @property
    def maximum_texture3d_width(self) -> int:
        """int: Maximum 3D texture width."""

    @property
    def maximum_texture3d_height(self) -> int:
        """int: Maximum 3D texture height."""

    @property
    def maximum_texture3d_depth(self) -> int:
        """int: Maximum 3D texture depth."""

    @property
    def maximum_texture3d_width_alternate(self) -> int:
        """int: Alternate maximum 3D texture width, 0 if no alternate maximum 3D texture size is supported."""

    @property
    def maximum_texture3d_height_alternate(self) -> int:
        """int: Alternate maximum 3D texture height, 0 if no alternate maximum 3D texture size is supported."""

    @property
    def maximum_texture3d_depth_alternate(self) -> int:
        """int: Alternate maximum 3D texture depth, 0 if no alternate maximum 3D texture size is supported."""

    @property
    def maximum_texturecubemap_width(self) -> int:
        """int: Maximum cubemap texture width or height."""

    @property
    def maximum_texture1d_layered_width(self) -> int:
        """int: Maximum 1D layered texture width."""

    @property
    def maximum_texture1d_layered_layers(self) -> int:
        """int: Maximum layers in a 1D layered texture."""

    @property
    def maximum_texture2d_layered_width(self) -> int:
        """int: Maximum 2D layered texture width."""

    @property
    def maximum_texture2d_layered_height(self) -> int:
        """int: Maximum 2D layered texture height."""

    @property
    def maximum_texture2d_layered_layers(self) -> int:
        """int: Maximum layers in a 2D layered texture."""

    @property
    def maximum_texturecubemap_layered_width(self) -> int:
        """int: Maximum cubemap layered texture width or height."""

    @property
    def maximum_texturecubemap_layered_layers(self) -> int:
        """int: Maximum layers in a cubemap layered texture."""

    @property
    def maximum_surface1d_width(self) -> int:
        """int: Maximum 1D surface width."""

    @property
    def maximum_surface2d_width(self) -> int:
        """int: Maximum 2D surface width."""

    @property
    def maximum_surface2d_height(self) -> int:
        """int: Maximum 2D surface height."""

    @property
    def maximum_surface3d_width(self) -> int:
        """int: Maximum 3D surface width."""

    @property
    def maximum_surface3d_height(self) -> int:
        """int: Maximum 3D surface height."""

    @property
    def maximum_surface3d_depth(self) -> int:
        """int: Maximum 3D surface depth."""

    @property
    def maximum_surface1d_layered_width(self) -> int:
        """int: Maximum 1D layered surface width."""

    @property
    def maximum_surface1d_layered_layers(self) -> int:
        """int: Maximum layers in a 1D layered surface."""

    @property
    def maximum_surface2d_layered_width(self) -> int:
        """int: Maximum 2D layered surface width."""

    @property
    def maximum_surface2d_layered_height(self) -> int:
        """int: Maximum 2D layered surface height."""

    @property
    def maximum_surface2d_layered_layers(self) -> int:
        """int: Maximum layers in a 2D layered surface."""

    @property
    def maximum_surfacecubemap_width(self) -> int:
        """int: Maximum cubemap surface width."""

    @property
    def maximum_surfacecubemap_layered_width(self) -> int:
        """int: Maximum cubemap layered surface width."""

    @property
    def maximum_surfacecubemap_layered_layers(self) -> int:
        """int: Maximum layers in a cubemap layered surface."""

    @property
    def max_registers_per_block(self) -> int:
        """int: Maximum number of 32-bit registers available to a thread block."""

    @property
    def clock_rate(self) -> int:
        """int: Typical clock frequency in kilohertz."""

    @property
    def texture_alignment(self) -> int:
        """int: Alignment requirement for textures."""

    @property
    def texture_pitch_alignment(self) -> int:
        """int: Pitch alignment requirement for textures."""

    @property
    def gpu_overlap(self) -> bool:
        """bool: Device can possibly copy memory and execute a kernel concurrently. Deprecated. Use :attr:`~DeviceProperties.async_engine_count` instead."""

    @property
    def multiprocessor_count(self) -> int:
        """int: Number of multiprocessors on device."""

    @property
    def kernel_exec_timeout(self) -> bool:
        """bool: Specifies whether there is a run time limit on kernels."""

    @property
    def integrated(self) -> bool:
        """bool: Device is integrated with host memory."""

    @property
    def can_map_host_memory(self) -> bool:
        """bool: Device can map host memory into CUDA address space."""

    @property
    def compute_mode(self) -> int:
        """int: Compute mode (See CUcomputemode for details)."""

    @property
    def concurrent_kernels(self) -> bool:
        """bool: Device can possibly execute multiple kernels concurrently."""

    @property
    def ecc_enabled(self) -> bool:
        """bool: Device has ECC support enabled."""

    @property
    def pci_bus_id(self) -> int:
        """int: PCI bus ID of the device."""

    @property
    def pci_device_id(self) -> int:
        """int: PCI device ID of the device."""

    @property
    def pci_domain_id(self) -> int:
        """int: PCI domain ID of the device."""

    @property
    def tcc_driver(self) -> bool:
        """bool: Device is using TCC driver model."""

    @property
    def memory_clock_rate(self) -> int:
        """int: Peak memory clock frequency in kilohertz."""

    @property
    def global_memory_bus_width(self) -> int:
        """int: Global memory bus width in bits."""

    @property
    def l2_cache_size(self) -> int:
        """int: Size of L2 cache in bytes."""

    @property
    def max_threads_per_multiprocessor(self) -> int:
        """int: Maximum resident threads per multiprocessor."""

    @property
    def unified_addressing(self) -> bool:
        """bool: Device shares a unified address space with the host."""

    @property
    def compute_capability_major(self) -> int:
        """int: Major compute capability version number."""

    @property
    def compute_capability_minor(self) -> int:
        """int: Minor compute capability version number."""

    @property
    def global_l1_cache_supported(self) -> bool:
        """bool: Device supports caching globals in L1."""

    @property
    def local_l1_cache_supported(self) -> bool:
        """bool: Device supports caching locals in L1."""

    @property
    def max_shared_memory_per_multiprocessor(self) -> int:
        """int: Maximum shared memory available per multiprocessor in bytes."""

    @property
    def max_registers_per_multiprocessor(self) -> int:
        """int: Maximum number of 32-bit registers available per multiprocessor."""

    @property
    def managed_memory(self) -> bool:
        """bool: Device can allocate managed memory on this system."""

    @property
    def multi_gpu_board(self) -> bool:
        """bool: Device is on a multi-GPU board."""

    @property
    def multi_gpu_board_group_id(self) -> int:
        """int: Unique id for a group of devices on the same multi-GPU board."""

    @property
    def host_native_atomic_supported(self) -> bool:
        """bool: Link between the device and the host supports all native atomic operations."""

    @property
    def single_to_double_precision_perf_ratio(self) -> int:
        """int: Ratio of single precision performance (in floating-point operations per second) to double precision performance."""

    @property
    def pageable_memory_access(self) -> bool:
        """bool: Device supports coherently accessing pageable memory without calling cudaHostRegister on it."""

    @property
    def concurrent_managed_access(self) -> bool:
        """bool: Device can coherently access managed memory concurrently with the CPU."""

    @property
    def compute_preemption_supported(self) -> bool:
        """bool: Device supports compute preemption."""

    @property
    def can_use_host_pointer_for_registered_mem(self) -> bool:
        """bool: Device can access host registered memory at the same virtual address as the CPU."""

    @property
    def cooperative_launch(self) -> bool:
        """bool: Device supports launching cooperative kernels via cuLaunchCooperativeKernel."""

    @property
    def max_shared_memory_per_block_optin(self) -> int:
        """int: Maximum optin shared memory per block."""

    @property
    def pageable_memory_access_uses_host_page_tables(self) -> bool:
        """bool: Device accesses pageable memory via the host's page tables."""

    @property
    def direct_managed_mem_access_from_host(self) -> bool:
        """bool: The host can directly access managed memory on the device without migration."""

    @property
    def virtual_memory_management_supported(self) -> bool:
        """bool: Device supports virtual memory management APIs like cuMemAddressReserve, cuMemCreate, cuMemMap and related APIs."""

    @property
    def handle_type_posix_file_descriptor_supported(self) -> bool:
        """bool: Device supports exporting memory to a posix file descriptor with cuMemExportToShareableHandle, if requested via cuMemCreate."""

    @property
    def handle_type_win32_handle_supported(self) -> bool:
        """bool: Device supports exporting memory to a Win32 NT handle with cuMemExportToShareableHandle, if requested via cuMemCreate."""

    @property
    def handle_type_win32_kmt_handle_supported(self) -> bool:
        """bool: Device supports exporting memory to a Win32 KMT handle with cuMemExportToShareableHandle, if requested via cuMemCreate."""

    @property
    def max_blocks_per_multiprocessor(self) -> int:
        """int: Maximum number of blocks per multiprocessor."""

    @property
    def generic_compression_supported(self) -> bool:
        """bool: Device supports compression of memory."""

    @property
    def max_persisting_l2_cache_size(self) -> int:
        """int: Maximum L2 persisting lines capacity setting in bytes."""

    @property
    def max_access_policy_window_size(self) -> int:
        """int: Maximum value of CUaccessPolicyWindow.num_bytes."""

    @property
    def gpu_direct_rdma_with_cuda_vmm_supported(self) -> bool:
        """bool: Device supports specifying the GPUDirect RDMA flag with cuMemCreate."""

    @property
    def reserved_shared_memory_per_block(self) -> int:
        """int: Shared memory reserved by CUDA driver per block in bytes."""

    @property
    def sparse_cuda_array_supported(self) -> bool:
        """bool: Device supports sparse CUDA arrays and sparse CUDA mipmapped arrays."""

    @property
    def read_only_host_register_supported(self) -> bool:
        """bool: True if device supports using the cuMemHostRegister flag CU_MEMHOSTREGISTER_READ_ONLY to register memory that must be mapped as read-only to the GPU, False if not."""

    @property
    def memory_pools_supported(self) -> bool:
        """bool: Device supports using the cuMemAllocAsync and cuMemPool family of APIs."""

    @property
    def gpu_direct_rdma_supported(self) -> bool:
        """bool: Device supports GPUDirect RDMA APIs, like nvidia_p2p_get_pages (see https://docs.nvidia.com/cuda/gpudirect-rdma for more information)."""

    @property
    def gpu_direct_rdma_flush_writes_options(self) -> int:
        """int: The returned attribute shall be interpreted as a bitmask, where the individual bits are described by the CUflushGPUDirectRDMAWritesOptions enum."""

    @property
    def gpu_direct_rdma_writes_ordering(self) -> int:
        """int: GPUDirect RDMA writes to the device do not need to be flushed for consumers within the scope indicated by the returned attribute. See CUGPUDirectRDMAWritesOrdering for the numerical values returned here."""

    @property
    def mempool_supported_handle_types(self) -> int:
        """int: Handle types supported with mempool based IPC."""

    @property
    def deferred_mapping_cuda_array_supported(self) -> bool:
        """bool: Device supports deferred mapping CUDA arrays and CUDA mipmapped arrays."""

    @property
    def numa_config(self) -> int:
        """int: NUMA configuration of a device: value is of type CUdeviceNumaConfig enum."""

    @property
    def numa_id(self) -> int:
        """int: NUMA node ID of the GPU memory."""

    @property
    def multicast_supported(self) -> bool:
        """bool: Device supports switch multicast and reduction operations."""

    @property
    def surface_alignment(self) -> int:
        """int: Surface alignment requirement in bytes."""

    @property
    def async_engine_count(self) -> int:
        """int: Number of asynchronous engines."""

    @property
    def can_tex2d_gather(self) -> bool:
        """bool: True if device supports 2D texture gather operations, False if not."""

    @property
    def maximum_texture2d_gather_width(self) -> int:
        """int: Maximum 2D texture gather width."""

    @property
    def maximum_texture2d_gather_height(self) -> int:
        """int: Maximum 2D texture gather height."""

    @property
    def stream_priorities_supported(self) -> bool:
        """bool: True if device supports stream priorities, False if not."""

    @property
    def can_flush_remote_writes(self) -> bool:
        """bool: The CU_STREAM_WAIT_VALUE_FLUSH flag and the CU_STREAM_MEM_OP_FLUSH_REMOTE_WRITES MemOp are supported on the device. See Stream Memory Operations for additional details."""

    @property
    def host_register_supported(self) -> bool:
        """bool: Device supports host memory registration via cudaHostRegister."""

    @property
    def timeline_semaphore_interop_supported(self) -> bool:
        """bool: External timeline semaphore interop is supported on the device."""

    @property
    def cluster_launch(self) -> bool:
        """bool: Indicates device supports cluster launch."""

    @property
    def can_use_64_bit_stream_mem_ops(self) -> bool:
        """bool: 64-bit operations are supported in cuStreamBatchMemOp and related MemOp APIs."""

    @property
    def can_use_stream_wait_value_nor(self) -> bool:
        """bool: CU_STREAM_WAIT_VALUE_NOR is supported by MemOp APIs."""

    @property
    def dma_buf_supported(self) -> bool:
        """bool: Device supports buffer sharing with dma_buf mechanism."""

    @property
    def ipc_event_supported(self) -> bool:
        """bool: Device supports IPC Events."""

    @property
    def mem_sync_domain_count(self) -> int:
        """int: Number of memory domains the device supports."""

    @property
    def tensor_map_access_supported(self) -> bool:
        """bool: Device supports accessing memory using Tensor Map."""

    @property
    def handle_type_fabric_supported(self) -> bool:
        """bool: Device supports exporting memory to a fabric handle with cuMemExportToShareableHandle() or requested with cuMemCreate()."""

    @property
    def unified_function_pointers(self) -> bool:
        """bool: Device supports unified function pointers."""

    @property
    def mps_enabled(self) -> bool:
        """bool: Indicates if contexts created on this device will be shared via MPS."""

    @property
    def host_numa_id(self) -> int:
        """int: NUMA ID of the host node closest to the device. Returns -1 when system does not support NUMA."""

    @property
    def d3d12_cig_supported(self) -> bool:
        """bool: Device supports CIG with D3D12."""

    @property
    def mem_decompress_algorithm_mask(self) -> int:
        """int: The returned value shall be interpreted as a bitmask, where the individual bits are described by the CUmemDecompressAlgorithm enum."""

    @property
    def mem_decompress_maximum_length(self) -> int:
        """int: The returned value is the maximum length in bytes of a single decompress operation that is allowed."""

    @property
    def vulkan_cig_supported(self) -> bool:
        """bool: Device supports CIG with Vulkan."""

    @property
    def gpu_pci_device_id(self) -> int:
        """int: The combined 16-bit PCI device ID and 16-bit PCI vendor ID.

        Returns 0 if the driver does not support this query.
        """

    @property
    def gpu_pci_subsystem_id(self) -> int:
        """int: The combined 16-bit PCI subsystem ID and 16-bit PCI subsystem vendor ID.

        Returns 0 if the driver does not support this query.
        """

    @property
    def host_numa_virtual_memory_management_supported(self) -> bool:
        """bool: Device supports HOST_NUMA location with the virtual memory management APIs like cuMemCreate, cuMemMap and related APIs."""

    @property
    def host_numa_memory_pools_supported(self) -> bool:
        """bool: Device supports HOST_NUMA location with the cuMemAllocAsync and cuMemPool family of APIs."""

    @property
    def host_numa_multinode_ipc_supported(self) -> bool:
        """bool: Device supports HOST_NUMA location IPC between nodes in a multi-node system."""

    @property
    def host_memory_pools_supported(self) -> bool:
        """bool: Device supports HOST location with the cuMemAllocAsync and cuMemPool family of APIs."""

    @property
    def host_virtual_memory_management_supported(self) -> bool:
        """bool: Device supports HOST location with the virtual memory management APIs like cuMemCreate, cuMemMap and related APIs."""

    @property
    def host_alloc_dma_buf_supported(self) -> bool:
        """bool: Device supports page-locked host memory buffer sharing with dma_buf mechanism."""

    @property
    def only_partial_host_native_atomic_supported(self) -> bool:
        """bool: Link between the device and the host supports only some native atomic operations."""

class Device:
    """Represent a GPU and act as an entry point for cuda.core features.

    This is a singleton object that helps ensure interoperability
    across multiple libraries imported in the process to both see
    and use the same GPU device.

    While acting as the entry point, many other CUDA resources can be
    allocated such as streams and buffers. Any :obj:`~_context.Context` dependent
    resource created through this device, will continue to refer to
    this device's context.

    Newly returned :obj:`~_device.Device` objects are thread-local singletons
    for a specified device.

    Note
    ----
    Will not initialize the GPU.

    Parameters
    ----------
    device_id : int, optional
        Device ordinal to return a :obj:`~_device.Device` object for.
        Default value of `None` return the currently used device.

    """
    __slots__ = ('_device_id', '_memory_resource', '_has_inited', '_properties', '_resources', '_uuid', '_context', '__weakref__')

    def __new__(cls, device_id: Device | int | None=None) -> Device:
        ...

    def _check_context_initialized(self) -> None:
        ...

    @classmethod
    def get_all_devices(cls) -> tuple[Device, ...]:
        """
        Query the available device instances.

        Returns
        -------
        tuple of Device
            A tuple containing instances of available devices.
        """

    def to_system_device(self) -> 'cuda.core.system.Device':
        """
        Get the corresponding :class:`cuda.core.system.Device` (which is used
        for NVIDIA Management Library (NVML) access) for this
        :class:`cuda.core.Device` (which is used for CUDA access).

        The devices are mapped to one another by their UUID.

        Returns
        -------
        cuda.core.system.Device
            The corresponding system-level device instance used for NVML access.
        """

    @property
    def device_id(self) -> int:
        """Return device ordinal."""

    @property
    def pci_bus_id(self) -> str:
        """Return a PCI Bus Id string for this device."""

    def can_access_peer(self, peer: Device | int) -> bool:
        """Check if this device can access memory from the specified peer device.

        Queries whether peer-to-peer memory access is supported between this
        device and the specified peer device.

        Parameters
        ----------
        peer : Device | int
            The peer device to check accessibility to. Can be a :obj:`~_device.Device` object or device ID.
        """

    @property
    def uuid(self) -> str:
        """Return a UUID for the device.

        Returns 16-octets identifying the device. If the device is in
        MIG mode, returns its MIG UUID which uniquely identifies the
        subscribed MIG compute instance.

        Note
        ----
        MIG UUID is only returned when device is in MIG mode and the
        driver is older than CUDA 11.4.

        The UUID is cached after first access to avoid repeated CUDA API calls.

        """

    @property
    def name(self) -> str:
        """Return the device name."""

    @property
    def properties(self) -> DeviceProperties:
        """Return a :obj:`~_device.DeviceProperties` class with information about the device."""

    @property
    def resources(self) -> DeviceResources:
        """Return the hardware resource query namespace for this device."""

    @property
    def compute_capability(self) -> ComputeCapability:
        """Return a named tuple with 2 fields: major and minor."""

    @property
    def arch(self) -> str:
        """Return compute capability as a string (e.g., '75' for CC 7.5)."""

    @property
    def context(self) -> Context:
        """Return the :obj:`~_context.Context` associated with this device.

        Note
        ----
        Device must be initialized.

        """

    @property
    def memory_resource(self) -> MemoryResource:
        """Return :obj:`~_memory.MemoryResource` associated with this device."""

    @memory_resource.setter
    def memory_resource(self, mr: MemoryResource) -> None:
        ...

    @property
    def default_stream(self) -> Stream:
        """Return default CUDA :obj:`~_stream.Stream` associated with this device.

        The type of default stream returned depends on if the environment
        variable CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM is set.

        If set, returns a per-thread default stream. Otherwise returns
        the legacy stream.

        """

    def __int__(self) -> int:
        """Return device_id."""

    def __repr__(self) -> str:
        ...

    def __hash__(self) -> int:
        ...

    def __eq__(self, other: object) -> bool:
        ...

    def __reduce__(self) -> tuple[object, ...]:
        ...

    def set_current(self, ctx: Context | None=None) -> Context | None:
        """Set device to be used for GPU executions.

        Initializes CUDA and sets the calling thread to a valid CUDA
        context. By default the primary context is used, but optional `ctx`
        parameter can be used to explicitly supply a :obj:`~_context.Context` object.

        Providing a `ctx` causes the previous set context to be popped and returned.

        Parameters
        ----------
        ctx : :obj:`~_context.Context`, optional
            Optional context to push onto this device's current thread stack.

        Returns
        -------
        :obj:`~_context.Context`, optional
            Popped context.

        Examples
        --------
        Acts as an entry point of this object. Users always start a code by
        calling this method, e.g.

        >>> from cuda.core import Device
        >>> dev0 = Device(0)
        >>> dev0.set_current()
        >>> # ... do work on device 0 ...

        """

    def create_context(self, options: ContextOptions | None=None) -> Context:
        """Create a new :obj:`~_context.Context` object.

        Note
        ----
        The newly created context will not be set as current.

        Parameters
        ----------
        options : :obj:`~_context.ContextOptions`, optional
            Customizable dataclass for context creation options.

        Returns
        -------
        :obj:`~_context.Context`
            Newly created context object.

        """

    def create_stream(self, obj: IsStreamType | None=None, options: object=None) -> Stream:
        """Create a :obj:`~_stream.Stream` object.

        New stream objects can be created in two different ways:

        1) Create a new CUDA stream with customizable ``options``.
        2) Wrap an existing foreign `obj` supporting the ``__cuda_stream__`` protocol.

        Option (2) internally holds a reference to the foreign object
        such that the lifetime is managed.

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        obj : :obj:`~_stream.IsStreamType`, optional
            Any object supporting the ``__cuda_stream__`` protocol.
        options : :obj:`~_stream.StreamOptions`, optional
            Customizable dataclass for stream creation options.

        Returns
        -------
        :obj:`~_stream.Stream`
            Newly created stream object.

        """

    def create_event(self, options: EventOptions | None=None) -> Event:
        """Create an :obj:`~_event.Event` object without recording it to a :obj:`~_stream.Stream`.

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        options : :obj:`EventOptions`, optional
            Customizable dataclass for event creation options.

        Returns
        -------
        :obj:`~_event.Event`
            Newly created event object.

        """

    def allocate(self, size: int, *, stream: Stream | GraphBuilder) -> Buffer:
        """Allocate device memory from a specified stream.

        Allocates device memory of `size` bytes on the specified `stream`
        using the memory resource currently associated with this Device.

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        size : int
            Number of bytes to allocate.
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Keyword-only. The stream establishing the stream ordering semantic.
            Must be passed explicitly; pass ``self.default_stream`` to use
            the default stream.

        Returns
        -------
        :obj:`~_memory.Buffer`
            Newly created buffer object.

        """

    def sync(self) -> None:
        """Synchronize the device.

        Note
        ----
        Device must be initialized.

        """

    def create_graph_builder(self) -> GraphBuilder:
        """Create a new :obj:`~graph.GraphBuilder` object.

        Returns
        -------
        :obj:`~graph.GraphBuilder`
            Newly created graph builder object.

        """

    def create_opaque_array(self, options: OpaqueArrayOptions) -> OpaqueArray:
        """Create an :obj:`~cuda.core.texture.OpaqueArray` on the current device.

        Allocates an opaque, hardware-laid-out CUDA array for texture/surface
        access. The array is created in the current CUDA context, so make this
        device current with :meth:`set_current` before calling (mirroring
        :meth:`create_stream` / :meth:`create_event`).

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        options : :obj:`~cuda.core.texture.OpaqueArrayOptions`
            Allocation options (shape, format, channels, surface flag).

        Returns
        -------
        :obj:`~cuda.core.texture.OpaqueArray`
            Newly created opaque array.

        .. versionadded:: 1.1.0
        """

    def create_mipmapped_array(self, options: MipmappedArrayOptions) -> MipmappedArray:
        """Create a :obj:`~cuda.core.texture.MipmappedArray` on the current device.

        Allocates a mipmapped CUDA array for texture/surface access across
        levels. The array is created in the current CUDA context, so make this
        device current with :meth:`set_current` before calling (mirroring
        :meth:`create_stream` / :meth:`create_event`).

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        options : :obj:`~cuda.core.texture.MipmappedArrayOptions`
            Allocation options (shape, format, channels, levels, surface flag).

        Returns
        -------
        :obj:`~cuda.core.texture.MipmappedArray`
            Newly created mipmapped array.

        .. versionadded:: 1.1.0
        """

    def create_texture_object(self, *, resource: ResourceDescriptor, options: TextureObjectOptions | None=None) -> TextureObject:
        """Create a :obj:`~cuda.core.texture.TextureObject` on the current device.

        Binds a resource (an :obj:`~cuda.core.texture.OpaqueArray` /
        :obj:`~cuda.core.texture.MipmappedArray` / linear or pitch2d
        :obj:`~cuda.core.Buffer`, wrapped in a
        :obj:`~cuda.core.texture.ResourceDescriptor`) as a bindless texture for
        kernel-side sampled reads. The object is created in the current CUDA
        context, so make this device current with :meth:`set_current` before
        calling (mirroring :meth:`create_stream` / :meth:`create_event`).

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        resource : :obj:`~cuda.core.texture.ResourceDescriptor`
            The memory backing the texture.
        options : :obj:`~cuda.core.texture.TextureObjectOptions`
            Sampling state (address/filter/read modes, normalization, etc.).

        Returns
        -------
        :obj:`~cuda.core.texture.TextureObject`
            Newly created texture object.

        .. versionadded:: 1.1.0
        """

    def create_surface_object(self, *, resource: ResourceDescriptor) -> SurfaceObject:
        """Create a :obj:`~cuda.core.texture.SurfaceObject` on the current device.

        Binds an :obj:`~cuda.core.texture.OpaqueArray` (via a
        :obj:`~cuda.core.texture.ResourceDescriptor`) as a bindless surface for
        kernel-side typed load/store. The backing array must have been created
        with ``is_surface_load_store=True``. The object is created in the
        current CUDA context, so make this device current with
        :meth:`set_current` before calling (mirroring :meth:`create_stream` /
        :meth:`create_event`).

        Note
        ----
        Device must be initialized.

        Parameters
        ----------
        resource : :obj:`~cuda.core.texture.ResourceDescriptor`
            Must wrap an :obj:`~cuda.core.texture.OpaqueArray` allocated with
            ``is_surface_load_store=True``.

        Returns
        -------
        :obj:`~cuda.core.texture.SurfaceObject`
            Newly created surface object.

        .. versionadded:: 1.1.0
        """
_tls = threading.local()
_lock = threading.Lock()