Skip to content

Commit 0778d50

Browse files
committed
Use our Python allocator on free-threaded builds, but do it correctly with PyMem_Malloc.
1 parent 5f661f4 commit 0778d50

File tree

1 file changed

+14
-28
lines changed

1 file changed

+14
-28
lines changed

src/greenlet/greenlet_allocator.hpp

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,6 @@
1010

1111
namespace greenlet
1212
{
13-
#if defined(Py_GIL_DISABLED)
14-
// Python on free threaded builds says this
15-
// (https://docs.python.org/3/howto/free-threading-extensions.html#memory-allocation-apis):
16-
//
17-
// For thread-safety, the free-threaded build requires that only
18-
// Python objects are allocated using the object domain, and that all
19-
// Python object are allocated using that domain.
20-
//
21-
// This turns out to be important because the GC implementation on
22-
// free threaded Python uses internal mimalloc APIs to find allocated
23-
// objects. If we allocate non-PyObject objects using that API, then
24-
// Bad Things could happen, including crashes and improper results.
25-
// So in that case, we revert to standard C++ allocation.
26-
27-
template <class T>
28-
struct PythonAllocator : public std::allocator<T> {
29-
// This member is deprecated in C++17 and removed in C++20
30-
template< class U >
31-
struct rebind {
32-
typedef PythonAllocator<U> other;
33-
};
34-
};
35-
36-
#else
3713
// This allocator is stateless; all instances are identical.
3814
// It can *ONLY* be used when we're sure we're holding the GIL
3915
// (Python's allocators require the GIL).
@@ -60,21 +36,32 @@ namespace greenlet
6036
T* allocate(size_t number_objects, const void* UNUSED(hint)=0)
6137
{
6238
void* p;
63-
if (number_objects == 1)
39+
if (number_objects == 1) {
40+
#ifdef Py_GIL_DISABLED
41+
p = PyMem_Malloc(sizeof(T) * number_objects);
42+
#else
6443
p = PyObject_Malloc(sizeof(T));
65-
else
44+
#endif
45+
}
46+
else {
6647
p = PyMem_Malloc(sizeof(T) * number_objects);
48+
}
6749
return static_cast<T*>(p);
6850
}
6951

7052
void deallocate(T* t, size_t n)
7153
{
7254
void* p = t;
7355
if (n == 1) {
56+
#ifdef Py_GIL_DISABLED
57+
PyMem_Free(p);
58+
#else
7459
PyObject_Free(p);
60+
#endif
7561
}
76-
else
62+
else {
7763
PyMem_Free(p);
64+
}
7865
}
7966
// This member is deprecated in C++17 and removed in C++20
8067
template< class U >
@@ -83,7 +70,6 @@ namespace greenlet
8370
};
8471

8572
};
86-
#endif // allocator type
8773
}
8874

8975
#endif

0 commit comments

Comments
 (0)