class_docstr: An owning buffer that represents device memory.
  
  This class isn't meant to be used throughout cuDF. Instead, it
  standardizes data owning by wrapping any data object that
  represents device memory. Multiple `Buffer` instances, which are
  the ones used throughout cuDF, can then refer to the same
  `BufferOwner` instance.
  
  In order to implement copy-on-write and spillable buffers, we need the
  ability to detect external access to the underlying memory. We say that
  the buffer has been exposed if the device pointer (integer or void*) has
  been accessed outside of BufferOwner. In this case, we have no control
  over knowing if the data is being modified by a third party.
  
  Use `_from_device_memory` and `_from_host_memory` to create
  a new instance from either device or host memory respectively.
class_docstr_tok: ["An","owning","buffer","that","represents","device","memory",".","This","class","is","n't","meant","to","be","used","throughout","cuDF",".","Instead",",","it","standardizes","data","owning","by","wrapping","any","data","object","that","represents","device","memory",".","Multiple","`","Buffer","`","instances",",","which","are","the","ones","used","throughout","cuDF",",","can","then","refer","to","the","same","`","BufferOwner","`","instance",".","In","order","to","implement","copy-on-write","and","spillable","buffers",",","we","need","the","ability","to","detect","external","access","to","the","underlying","memory",".","We","say","that","the","buffer","has","been","exposed","if","the","device","pointer","(","integer","or","void","*",")","has","been","accessed","outside","of","BufferOwner",".","In","this","case",",","we","have","no","control","over","knowing","if","the","data","is","being","modified","by","a","third","party",".","Use","`","_from_device_memory","`","and","`","_from_host_memory","`","to","create","a","new","instance","from","either","device","or","host","memory","respectively","."]
docstr: Create from an object providing a `__cuda_array_interface__`.
  
  No data is being copied.
  
  Parameters
  ----------
  data : device-buffer-like
      An object implementing the CUDA Array Interface.
  exposed : bool
      Mark the buffer as permanently exposed. This is used by
      ExposureTrackedBuffer to determine when a deep copy is required
      and by SpillableBuffer to mark the buffer unspillable.
  
  Returns
  -------
  BufferOwner
      BufferOwner wrapping `data`
  
  Raises
  ------
  AttributeError
      If data does not support the cuda array interface
  ValueError
      If the resulting buffer has negative size
code: def _from_device_memory(cls, data: Any, exposed: bool) -> Self:
      """Create from an object providing a `__cuda_array_interface__`.
  
      No data is being copied.
  
      Parameters
      ----------
      data : device-buffer-like
          An object implementing the CUDA Array Interface.
      exposed : bool
          Mark the buffer as permanently exposed. This is used by
          ExposureTrackedBuffer to determine when a deep copy is required
          and by SpillableBuffer to mark the buffer unspillable.
  
      Returns
      -------
      BufferOwner
          BufferOwner wrapping `data`
  
      Raises
      ------
      AttributeError
          If data does not support the cuda array interface
      ValueError
          If the resulting buffer has negative size
      """
  
      # Bypass `__init__` and initialize attributes manually
      ret = cls.__new__(cls)
      ret._owner = data
      ret._exposed = exposed
      ret._slices = weakref.WeakSet()
      if isinstance(data, rmm.DeviceBuffer):  # Common case shortcut
          ret._ptr = data.ptr
          ret._size = data.size
      else:
          ret._ptr, ret._size = get_ptr_and_size(
              data.__cuda_array_interface__
          )
      if ret.size < 0:
          raise ValueError("size cannot be negative")
      return ret
  
imports: from __future__ import annotations
  import math
  import pickle
  import weakref
  from types import SimpleNamespace
  from typing import Any, Dict, Literal, Mapping, Optional, Sequence, Tuple
  import numpy
  from typing_extensions import Self
  import rmm
  import cudf
  from cudf.core.abc import Serializable
  from cudf.utils.string import format_bytes
label_desc: Use image node_id 2 for calling the BufferOwner obj's underlying member method code with example usage: obj._from_device_memory(cls, data, exposed) and returns: ret