-
Notifications
You must be signed in to change notification settings - Fork 32
ENH: Followup audit of FT build #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
448c5ce
40d94e8
13fd129
9b53e14
7fc4205
52ee6de
17eb68a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,12 @@ import warnings | |
|
|
||
| WARN_ZERO_ALLOC = False | ||
|
|
||
| cdef bint CYTHON_FREE_THREADING | ||
|
|
||
| IF CYTHON_FREE_THREADING: | ||
| from libcpp.mutex cimport once_flag, call_once | ||
| cdef once_flag _lazy_import_lock | ||
|
|
||
| cdef class PyMalloc: | ||
| cdef void _set(self, malloc_t malloc): | ||
| self.malloc = malloc | ||
|
|
@@ -17,6 +23,24 @@ cdef PyMalloc WrapMalloc(malloc_t malloc): | |
| o._set(malloc) | ||
| return o | ||
|
|
||
| cdef class PyCalloc: | ||
| cdef void _set(self, calloc_t calloc): | ||
| self.calloc = calloc | ||
|
|
||
| cdef PyCalloc WrapCalloc(calloc_t calloc): | ||
| cdef PyCalloc o = PyCalloc() | ||
| o._set(calloc) | ||
| return o | ||
|
|
||
| cdef class PyRealloc: | ||
| cdef void _set(self, realloc_t realloc): | ||
| self.realloc = realloc | ||
|
|
||
| cdef PyRealloc WrapRealloc(realloc_t realloc): | ||
| cdef PyRealloc o = PyRealloc() | ||
| o._set(realloc) | ||
| return o | ||
|
|
||
| cdef class PyFree: | ||
| cdef void _set(self, free_t free): | ||
| self.free = free | ||
|
|
@@ -27,6 +51,8 @@ cdef PyFree WrapFree(free_t free): | |
| return o | ||
|
|
||
| Default_Malloc = WrapMalloc(PyMem_Malloc) | ||
| Default_Calloc = WrapCalloc(PyMem_Calloc) | ||
| Default_Realloc = WrapRealloc(PyMem_Realloc) | ||
| Default_Free = WrapFree(PyMem_Free) | ||
|
|
||
| cdef class Pool: | ||
|
|
@@ -43,15 +69,21 @@ cdef class Pool: | |
| size (size_t): The current size (in bytes) allocated by the pool. | ||
| addresses (dict): The currently allocated addresses and their sizes. Read-only. | ||
| pymalloc (PyMalloc): The allocator to use (default uses PyMem_Malloc). | ||
| pycalloc (PyCalloc): The allocator to use (default uses PyMem_Calloc). | ||
| pyrealloc (PyRealloc): The allocator to use (default uses PyMem_Realloc). | ||
| pyfree (PyFree): The free to use (default uses PyMem_Free). | ||
| """ | ||
|
|
||
| def __cinit__(self, PyMalloc pymalloc=Default_Malloc, | ||
| PyCalloc pycalloc = Default_Calloc, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is backwards incompatible. A user who was instantiated the class with something like When adding new arguments to a function with defaults, the new arguments need to be placed after the current ones. |
||
| PyRealloc pyrealloc = Default_Realloc, | ||
| PyFree pyfree=Default_Free): | ||
| self.size = 0 | ||
| self.addresses = {} | ||
| self.refs = [] | ||
| self.pymalloc = pymalloc | ||
| self.pycalloc = pycalloc | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately this will be more disruptive than a reasonable person would expect. We build against If a public class changes size in Cython, it's no longer binary-compatible. This means we'll need to make this a major version increment, and we'd need to do updates across our dependency chain to use the new version. |
||
| self.pyrealloc = pyrealloc | ||
| self.pyfree = pyfree | ||
|
|
||
| def __dealloc__(self): | ||
|
|
@@ -69,10 +101,9 @@ cdef class Pool: | |
| """ | ||
| if WARN_ZERO_ALLOC and (number == 0 or elem_size == 0): | ||
| warnings.warn("Allocating zero bytes") | ||
| cdef void* p = self.pymalloc.malloc(number * elem_size) | ||
| cdef void* p = self.pycalloc.calloc(number * elem_size) | ||
| if p == NULL: | ||
| raise MemoryError("Error assigning %d bytes" % (number * elem_size)) | ||
| memset(p, 0, number * elem_size) | ||
| self.addresses[<size_t>p] = number * elem_size | ||
| self.size += number * elem_size | ||
| return p | ||
|
|
@@ -84,18 +115,21 @@ cdef class Pool: | |
|
|
||
| If p is not in the Pool or new_size is 0, a MemoryError is raised. | ||
| """ | ||
| cdef void* p_new | ||
| if <size_t>p not in self.addresses: | ||
| raise ValueError("Pointer %d not found in Pool %s" % (<size_t>p, self.addresses)) | ||
| if new_size == 0: | ||
| raise ValueError("Realloc requires new_size > 0") | ||
| assert new_size > self.addresses[<size_t>p] | ||
| cdef void* new_ptr = self.alloc(1, new_size) | ||
| if new_ptr == NULL: | ||
| old_size_val = self.addresses[<size_t>p] | ||
| p_new = self.pyrealloc.realloc(p, new_size) | ||
| if p_new == NULL: | ||
| raise MemoryError("Error reallocating to %d bytes" % new_size) | ||
| memcpy(new_ptr, p, self.addresses[<size_t>p]) | ||
| self.free(p) | ||
| self.addresses[<size_t>new_ptr] = new_size | ||
| return new_ptr | ||
| # Resize in place | ||
| self.addresses.pop(<size_t>p_old) | ||
| self.addresses[<size_t>p_new] = new_size | ||
| self.size = (self.size - old_size_val) + new_size | ||
| return p_new | ||
|
|
||
| cdef void free(self, void* p) except *: | ||
| """Frees the memory block pointed to by p, which must have been returned | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're adding to the public API, you should explain in the PR description why. Also,
callocmethod is added to the implementation but not here.