@@ -31,16 +31,25 @@ import numbers
3131from cpython cimport Py_buffer
3232from libc.string cimport memcpy
3333
34- from mkl._mkl_service cimport mkl_malloc, mkl_free
34+ from mkl._mkl_service cimport mkl_malloc, mkl_realloc, mkl_free
35+
36+ cdef extern from " stdatomic.h" nogil:
37+ ctypedef int atomic_int " _Atomic int"
38+ void atomic_init(atomic_int * obj, int value)
39+ int atomic_fetch_add(atomic_int * obj, int value)
40+ int atomic_fetch_sub(atomic_int * obj, int value)
41+ int atomic_load(atomic_int * obj)
3542
3643
3744cdef class MKLMemory:
3845 cdef void * _memory_ptr
3946 cdef Py_ssize_t nbytes
47+ cdef atomic_int exported_buffers
4048
4149 cdef _cinit_empty(self ):
4250 self ._memory_ptr = NULL
4351 self .nbytes = 0
52+ atomic_init(& self .exported_buffers, 0 )
4453
4554 cdef _cinit_alloc(self , Py_ssize_t nbytes, Py_ssize_t alignment):
4655 self ._cinit_empty()
@@ -100,5 +109,23 @@ cdef class MKLMemory:
100109 buffer .strides = & buffer .itemsize
101110 buffer .suboffsets = NULL # for pointer arrays only
102111
112+ atomic_fetch_add(& self .exported_buffers, 1 )
113+
103114 def __releasebuffer__ (self , Py_buffer *buffer ):
104- pass
115+ atomic_fetch_sub(& self .exported_buffers, 1 )
116+
117+ def realloc (self , Py_ssize_t new_nbytes ):
118+ if atomic_load(& self .exported_buffers) > 0 :
119+ raise BufferError(" Cannot realloc memory while there are exported buffers." )
120+ if new_nbytes <= 0 :
121+ raise ValueError (" New number of bytes must be positive." )
122+
123+ cdef void * p
124+ with nogil:
125+ p = mkl_realloc(self ._memory_ptr, new_nbytes)
126+
127+ if not p:
128+ raise MemoryError (" MKL memory reallocation failed." )
129+
130+ self ._memory_ptr = p
131+ self .nbytes = new_nbytes
0 commit comments