@@ -8,6 +8,12 @@ import warnings
88
99WARN_ZERO_ALLOC = False
1010
11+ cdef bint CYTHON_FREE_THREADING
12+
13+ IF CYTHON_FREE_THREADING:
14+ from libcpp.mutex cimport once_flag, call_once
15+ cdef once_flag _lazy_import_lock
16+
1117cdef class PyMalloc:
1218 cdef void _set(self , malloc_t malloc):
1319 self .malloc = malloc
@@ -17,6 +23,24 @@ cdef PyMalloc WrapMalloc(malloc_t malloc):
1723 o._set(malloc)
1824 return o
1925
26+ cdef class PyCalloc:
27+ cdef void _set(self , calloc_t calloc):
28+ self .calloc = calloc
29+
30+ cdef PyCalloc WrapCalloc(calloc_t calloc):
31+ cdef PyCalloc o = PyCalloc()
32+ o._set(calloc)
33+ return o
34+
35+ cdef class PyRealloc:
36+ cdef void _set(self , realloc_t realloc):
37+ self .realloc = realloc
38+
39+ cdef PyRealloc WrapRealloc(realloc_t realloc):
40+ cdef PyRealloc o = PyRealloc()
41+ o._set(realloc)
42+ return o
43+
2044cdef class PyFree:
2145 cdef void _set(self , free_t free):
2246 self .free = free
@@ -27,6 +51,8 @@ cdef PyFree WrapFree(free_t free):
2751 return o
2852
2953Default_Malloc = WrapMalloc(PyMem_Malloc)
54+ Default_Calloc = WrapCalloc(PyMem_Calloc)
55+ Default_Realloc = WrapRealloc(PyMem_Realloc)
3056Default_Free = WrapFree(PyMem_Free)
3157
3258cdef class Pool:
@@ -43,15 +69,21 @@ cdef class Pool:
4369 size (size_t): The current size (in bytes) allocated by the pool.
4470 addresses (dict): The currently allocated addresses and their sizes. Read-only.
4571 pymalloc (PyMalloc): The allocator to use (default uses PyMem_Malloc).
72+ pycalloc (PyCalloc): The allocator to use (default uses PyMem_Calloc).
73+ pyrealloc (PyRealloc): The allocator to use (default uses PyMem_Realloc).
4674 pyfree (PyFree): The free to use (default uses PyMem_Free).
4775 """
4876
4977 def __cinit__ (self , PyMalloc pymalloc = Default_Malloc,
78+ PyCalloc pycalloc = Default_Calloc,
79+ PyRealloc pyrealloc = Default_Realloc,
5080 PyFree pyfree = Default_Free):
5181 self .size = 0
5282 self .addresses = {}
5383 self .refs = []
5484 self .pymalloc = pymalloc
85+ self .pycalloc = pycalloc
86+ self .pyrealloc = pyrealloc
5587 self .pyfree = pyfree
5688
5789 def __dealloc__ (self ):
@@ -69,10 +101,9 @@ cdef class Pool:
69101 """
70102 if WARN_ZERO_ALLOC and (number == 0 or elem_size == 0 ):
71103 warnings.warn(" Allocating zero bytes" )
72- cdef void * p = self .pymalloc.malloc (number * elem_size)
104+ cdef void * p = self .pycalloc.calloc (number * elem_size)
73105 if p == NULL :
74106 raise MemoryError (" Error assigning %d bytes" % (number * elem_size))
75- memset(p, 0 , number * elem_size)
76107 self .addresses[< size_t> p] = number * elem_size
77108 self .size += number * elem_size
78109 return p
@@ -89,13 +120,12 @@ cdef class Pool:
89120 if new_size == 0 :
90121 raise ValueError (" Realloc requires new_size > 0" )
91122 assert new_size > self .addresses[< size_t> p]
92- cdef void * new_ptr = self .alloc( 1 , new_size)
93- if new_ptr == NULL :
123+ self .realloc(p , new_size)
124+ if p == NULL :
94125 raise MemoryError (" Error reallocating to %d bytes" % new_size)
95- memcpy(new_ptr, p, self .addresses[< size_t> p])
96- self .free(p)
97- self .addresses[< size_t> new_ptr] = new_size
98- return new_ptr
126+ # Resize in place
127+ self .addresses[< size_t> p] = new_size
128+ return p
99129
100130 cdef void free(self , void * p) except * :
101131 """ Frees the memory block pointed to by p, which must have been returned
0 commit comments