@@ -163,6 +163,19 @@ cdef class MKLMemory:
163163 address alignment of the allocation in bytes. Expected to be a
164164 power of two and to not exceed ``INT_MAX``. Defaults to the
165165 alignment of ``other`` in the copy form, and to `64` otherwise.
166+
167+ Exported buffers and the copy constructor keep :meth:`realloc` from moving
168+ the allocation while they use it, but :meth:`tobytes`, :attr:`nbytes`,
169+ :attr:`_pointer`, ``len()`` and ``repr()`` read it without doing so. Under
170+ the GIL none of these can overlap a resize. On a free-threaded build, when
171+ another thread can reach the object during a resize (see :meth:`realloc`),
172+ they may read freed memory, or a pointer and a size that do not belong
173+ together; as with :meth:`realloc`, arranging exclusive access is the
174+ caller's responsibility.
175+
176+ Pickling preserves the content, the alignment, the subclass and the
177+ instance ``__dict__``, but not attributes a subclass stores in
178+ ``__slots__``.
166179 """
167180 cdef void * _memory_ptr
168181 cdef Py_ssize_t _nbytes
@@ -390,6 +403,9 @@ cdef class MKLMemory:
390403 def tobytes (self ):
391404 """
392405 Constructs bytes object populated with copy of this allocation.
406+
407+ The copy does not hold the allocation in place, so it must not overlap
408+ a :meth:`realloc` from another thread.
393409 """
394410 cdef char * data_ptr = < char * > self ._memory_ptr
395411 return data_ptr[:self ._nbytes]
@@ -433,4 +449,5 @@ cdef class MKLMemory:
433449 else :
434450 args = (self .tobytes(), self ._alignment, cls )
435451
452+ # attributes held in __slots__ of a subclass are not carried over
436453 return (_mkl_memory_from_bytes, args, getattr (self , " __dict__" , None ))
0 commit comments