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

from __future__ import annotations

import cython
from cuda.core._memory._device_memory_resource import DeviceMemoryResource
from cuda.core._memory._ipc import IPCBufferDescriptor
from cuda.core._memory._pinned_memory_resource import PinnedMemoryResource
from cuda.core._stream import Stream
from cuda.core._utils.pycompat import BufferProtocol
from cuda.core.graph import GraphBuilder
from cuda.core.typing import DevicePointerType


class Buffer:
    """Represent a handle to allocated memory.

    This generic object provides a unified representation for how
    different memory resources are to give access to their memory
    allocations.

    Support for data interchange mechanisms are provided by DLPack.

    Note
    ----
    Pickling an IPC-enabled :class:`Buffer` embeds an
    :class:`~_memory.IPCBufferDescriptor`. Unpickling reconstructs the buffer
    by calling :meth:`from_ipc_descriptor` and therefore performs an IPC
    import. Do not unpickle buffers from untrusted sources.
    """

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

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

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

    @classmethod
    def _init(cls, ptr: DevicePointerType, size: int, mr: MemoryResource | None=None, ipc_descriptor: IPCBufferDescriptor | None=None, owner: object | None=None) -> Buffer:
        """Create a Buffer from a raw pointer.

        When ``mr`` is provided, the buffer takes ownership: ``mr.deallocate()``
        is called when the buffer is closed or garbage collected.  When ``owner``
        is provided, the owner is kept alive but no deallocation is performed.
        """

    @staticmethod
    def _reduce_helper(mr, ipc_descriptor):
        ...

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

    @staticmethod
    def from_handle(ptr: DevicePointerType, size: int, mr: MemoryResource | None=None, owner: object | None=None) -> Buffer:
        """Create a new :class:`Buffer` object from a pointer.

        Parameters
        ----------
        ptr : :obj:`~_memory.DevicePointerType`
            Allocated buffer handle object
        size : int
            Memory size of the buffer
        mr : :obj:`~_memory.MemoryResource`, optional
            Memory resource associated with the buffer.  When provided,
            :meth:`MemoryResource.deallocate` is called when the buffer is
            closed or garbage collected.
        owner : object, optional
            An object holding external allocation that the ``ptr`` points to.
            The reference is kept as long as the buffer is alive.
            The ``owner`` and ``mr`` cannot be specified together.

        Note
        ----
        When neither ``mr`` nor ``owner`` is specified, this creates a
        non-owning reference.  The pointer will NOT be freed when the
        :class:`Buffer` is closed or garbage collected.
        """

    @classmethod
    def from_ipc_descriptor(cls, mr: DeviceMemoryResource | PinnedMemoryResource, ipc_descriptor: IPCBufferDescriptor, *, stream: Stream) -> Buffer:
        """Import a buffer that was exported from another process.

        Parameters
        ----------
        mr : :obj:`~_memory.DeviceMemoryResource` | :obj:`~_memory.PinnedMemoryResource`
            The IPC-enabled memory resource matching the exporting process.
        ipc_descriptor : :obj:`~_memory.IPCBufferDescriptor`
            The descriptor exported from another process.
        stream : :obj:`~_stream.Stream`
            Keyword-only. The stream used for asynchronous deallocation when
            the buffer is closed or garbage collected.

        Note
        ----
        The descriptor payload and ``size`` are supplied by the exporting peer
        and must be treated as untrusted input unless the peer is known to be
        cooperating.
        """

    @property
    @cython.critical_section
    def ipc_descriptor(self) -> IPCBufferDescriptor:
        """Descriptor for sharing this buffer with other processes."""

    def close(self, stream: Stream | GraphBuilder | None=None) -> None:
        """Deallocate this buffer asynchronously on the given stream.

        This buffer is released back to their memory resource
        asynchronously on the given stream.

        Parameters
        ----------
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`, optional
            The stream object to use for asynchronous deallocation. If None,
            the deallocation stream stored in the handle is used.
        """

    def __enter__(self):
        ...

    def __exit__(self, exc_type, exc_val, exc_tb):
        ...

    def copy_to(self, dst: Buffer | None=None, *, stream: Stream | GraphBuilder) -> Buffer:
        """Copy from this buffer to the dst buffer asynchronously on the given stream.

        Copies the data from this buffer to the provided dst buffer.
        If the dst buffer is not provided, then a new buffer is first
        allocated using the associated memory resource before the copy.

        Parameters
        ----------
        dst : :obj:`~_memory.Buffer`, optional
            Destination buffer to copy data to. If not provided, a new buffer
            is allocated using this buffer's memory resource.
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Keyword argument specifying the stream for the
            asynchronous copy

        """

    def copy_from(self, src: Buffer, *, stream: Stream | GraphBuilder) -> None:
        """Copy from the src buffer to this buffer asynchronously on the given stream.

        Parameters
        ----------
        src : :obj:`~_memory.Buffer`
            Source buffer to copy data from
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Keyword argument specifying the stream for the
            asynchronous copy

        """

    def fill(self, value: int | BufferProtocol, *, stream: Stream | GraphBuilder) -> None:
        """Fill this buffer with a repeating byte pattern.

        Parameters
        ----------
        value : int | :obj:`collections.abc.Buffer`
            - int: Must be in range [0, 256). Converted to 1 byte.
            - :obj:`collections.abc.Buffer`: Must be 1, 2, or 4 bytes.
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Stream for the asynchronous fill operation.

        Raises
        ------
        TypeError
            If value is not an int and does not support the buffer protocol.
        ValueError
            If value byte length is not 1, 2, or 4.
            If buffer size is not divisible by value byte length.
        OverflowError
            If int value is outside [0, 256).

        """

    def __dlpack__(self, *, stream: int | None=None, max_version: tuple[int, int] | None=None, dl_device: tuple[int, int] | None=None, copy: bool | None=None) -> object:
        ...

    def __dlpack_device__(self) -> tuple[int, int]:
        ...

    def __buffer__(self, flags: int, /) -> memoryview:
        ...

    def __release_buffer__(self, buffer: memoryview, /) -> None:
        ...

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

    @property
    def handle(self) -> int:
        """Return the buffer handle object.

        .. caution::

            This handle is a Python object. To get the memory address of the underlying C
            handle, call ``int(Buffer.handle)``.
        """

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

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

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

    @property
    def is_device_accessible(self) -> bool:
        """Return True if this buffer can be accessed by the GPU, otherwise False."""

    @property
    def is_host_accessible(self) -> bool:
        """Return True if this buffer can be accessed by the CPU, otherwise False."""

    @property
    def is_managed(self) -> bool:
        """Return True if this buffer is CUDA managed (unified) memory, otherwise False."""

    @property
    def is_mapped(self) -> bool:
        """Return True if this buffer is mapped into the process via IPC."""

    @property
    def memory_resource(self) -> MemoryResource:
        """Return the memory resource associated with this buffer."""

    @property
    def size(self) -> int:
        """Return the memory size of this buffer."""

    @property
    def owner(self) -> object:
        """Return the object holding external allocation."""

class MemoryResource:
    """Abstract base class for memory resources that manage allocation and
    deallocation of buffers.

    Subclasses must implement methods for allocating and deallocation, as well
    as properties associated with this memory resource from which all allocated
    buffers will inherit. (Since all :class:`Buffer` instances allocated and
    returned by the :meth:`allocate` method would hold a reference to self, the
    buffer properties are retrieved simply by looking up the underlying memory
    resource's respective property.)
    """

    def allocate(self, size: int, *, stream: Stream | GraphBuilder) -> Buffer:
        """Allocate a buffer of the requested size.

        Parameters
        ----------
        size : int
            The size of the buffer to allocate, in bytes.
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Keyword-only. The stream on which to perform the allocation
            asynchronously. Must be passed explicitly; pass
            ``device.default_stream`` to use the default stream.

        Returns
        -------
        Buffer
            The allocated buffer object, which can be used for device or host operations
            depending on the resource's properties.
        """

    def deallocate(self, ptr: DevicePointerType, size: int, *, stream: Stream | GraphBuilder) -> None:
        """Deallocate a buffer previously allocated by this resource.

        Parameters
        ----------
        ptr : :obj:`~_memory.DevicePointerType`
            The pointer or handle to the buffer to deallocate.
        size : int
            The size of the buffer to deallocate, in bytes.
        stream : :obj:`~_stream.Stream` | :obj:`~graph.GraphBuilder`
            Keyword-only. The stream on which to perform the deallocation
            asynchronously. Must be passed explicitly; pass
            ``device.default_stream`` to use the default stream.
        """

    @property
    def is_device_accessible(self) -> bool:
        """Whether buffers allocated by this resource are device-accessible."""

    @property
    def is_host_accessible(self) -> bool:
        """Whether buffers allocated by this resource are host-accessible."""

    @property
    def is_managed(self) -> bool:
        """Whether buffers allocated by this resource are CUDA managed (unified) memory."""

    @property
    def device_id(self) -> int:
        """Device ID associated with this memory resource, or -1 if not applicable."""
__all__ = ['Buffer', 'MemoryResource']