Skip to content

Commit f522916

Browse files
rparolinclaude
andcommitted
refactor(cuda.core): narrow Buffer.from_handle to Buffer-only (R3)
Per Leo's review on PR #1775 (_buffer.pyx:135), make Buffer.from_handle a @staticmethod that always returns Buffer. Subclass-aware construction stays available via the private @classmethod Buffer._init, which is what Leo asked for ("use a private method for handling subclasses for now"). ManagedBuffer gains its own @classmethod from_handle that wraps cls._init, so user-facing call sites like ManagedBuffer.from_handle(ptr, size, owner=plain) continue to work unchanged. The narrowly-scoped subclass factory is on the subclass itself, not bolted onto Buffer's public surface. This addresses R3's spirit: cuda.core's public APIs no longer advertise generic subclass-construction support that conflicts with the broader subclassing story tracked in #750 / #1989. No test changes; behavior preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent df928a0 commit f522916

2 files changed

Lines changed: 33 additions & 9 deletions

File tree

cuda_core/cuda/core/_memory/_buffer.pyx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,8 @@ cdef class Buffer:
131131
# Must not serialize the parent's stream!
132132
return Buffer._reduce_helper, (self.memory_resource, self.get_ipc_descriptor())
133133

134-
@classmethod
134+
@staticmethod
135135
def from_handle(
136-
cls,
137136
ptr: DevicePointerT, size_t size, mr: MemoryResource | None = None,
138137
owner: object | None = None,
139138
) -> Buffer:
@@ -159,11 +158,8 @@ cdef class Buffer:
159158
When neither ``mr`` nor ``owner`` is specified, this creates a
160159
non-owning reference. The pointer will NOT be freed when the
161160
:class:`Buffer` is closed or garbage collected.
162-
163-
Subclasses inherit this method via :meth:`Buffer._init`, so e.g.
164-
``ManagedBuffer.from_handle(ptr, size)`` returns a ``ManagedBuffer``.
165161
"""
166-
return cls._init(ptr, size, mr=mr, owner=owner)
162+
return Buffer._init(ptr, size, mr=mr, owner=owner)
167163

168164
@classmethod
169165
def from_ipc_descriptor(

cuda_core/cuda/core/_memory/_managed_buffer.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from cuda.core._utils.cuda_utils import driver, handle_return
1313

1414
if TYPE_CHECKING:
15+
from cuda.core._memory._buffer import MemoryResource
1516
from cuda.core._stream import Stream
1617
from cuda.core.graph import GraphBuilder
1718

@@ -101,9 +102,7 @@ class ManagedBuffer(Buffer):
101102
"""Managed (unified) memory buffer with a property-style advice API.
102103
103104
Returned by :meth:`ManagedMemoryResource.allocate`, or wrap an
104-
existing managed-memory pointer with :meth:`Buffer.from_handle`
105-
(which dispatches by class — ``ManagedBuffer.from_handle(...)``
106-
returns a ``ManagedBuffer``).
105+
existing managed-memory pointer with :meth:`ManagedBuffer.from_handle`.
107106
108107
Examples
109108
--------
@@ -121,6 +120,35 @@ class ManagedBuffer(Buffer):
121120
advice.
122121
"""
123122

123+
@classmethod
124+
def from_handle(
125+
cls,
126+
ptr,
127+
size: int,
128+
mr: MemoryResource | None = None,
129+
owner: object | None = None,
130+
) -> ManagedBuffer:
131+
"""Wrap an existing managed-memory pointer in a :class:`ManagedBuffer`.
132+
133+
Use this when you have an externally-allocated managed pointer
134+
and want the property-style advice API (:attr:`read_mostly`,
135+
:attr:`preferred_location`, :attr:`accessed_by`).
136+
137+
Parameters
138+
----------
139+
ptr : :obj:`~_memory.DevicePointerT`
140+
Pointer to a managed allocation.
141+
size : int
142+
Allocation size in bytes.
143+
mr : :obj:`~_memory.MemoryResource`, optional
144+
Memory resource that owns ``ptr``. When provided, its
145+
``deallocate`` is called when the buffer is closed.
146+
owner : object, optional
147+
An object that keeps the underlying allocation alive.
148+
``owner`` and ``mr`` cannot both be specified.
149+
"""
150+
return cls._init(ptr, size, mr=mr, owner=owner)
151+
124152
@property
125153
def read_mostly(self) -> bool:
126154
"""Whether ``set_read_mostly`` advice is currently applied."""

0 commit comments

Comments
 (0)