greenlet_allocator.hpp 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #ifndef GREENLET_ALLOCATOR_HPP
  2. #define GREENLET_ALLOCATOR_HPP
  3. #define PY_SSIZE_T_CLEAN
  4. #include <Python.h>
  5. #include <memory>
  6. #include "greenlet_compiler_compat.hpp"
  7. #include "greenlet_cpython_compat.hpp"
  8. namespace greenlet
  9. {
  10. // This allocator is stateless; all instances are identical.
  11. // It can *ONLY* be used when we're sure we're holding the GIL
  12. // (Python's allocators require the GIL).
  13. template <class T>
  14. struct PythonAllocator : public std::allocator<T> {
  15. PythonAllocator(const PythonAllocator& UNUSED(other))
  16. : std::allocator<T>()
  17. {
  18. }
  19. PythonAllocator(const std::allocator<T> other)
  20. : std::allocator<T>(other)
  21. {}
  22. template <class U>
  23. PythonAllocator(const std::allocator<U>& other)
  24. : std::allocator<T>(other)
  25. {
  26. }
  27. PythonAllocator() : std::allocator<T>() {}
  28. T* allocate(size_t number_objects, const void* UNUSED(hint)=0)
  29. {
  30. void* p;
  31. if (number_objects == 1) {
  32. #ifdef Py_GIL_DISABLED
  33. p = PyMem_Malloc(sizeof(T) * number_objects);
  34. #else
  35. p = PyObject_Malloc(sizeof(T));
  36. #endif
  37. }
  38. else {
  39. p = PyMem_Malloc(sizeof(T) * number_objects);
  40. }
  41. return static_cast<T*>(p);
  42. }
  43. void deallocate(T* t, size_t n)
  44. {
  45. void* p = t;
  46. if (n == 1) {
  47. #ifdef Py_GIL_DISABLED
  48. PyMem_Free(p);
  49. #else
  50. PyObject_Free(p);
  51. #endif
  52. }
  53. else {
  54. PyMem_Free(p);
  55. }
  56. }
  57. // This member is deprecated in C++17 and removed in C++20
  58. template< class U >
  59. struct rebind {
  60. typedef PythonAllocator<U> other;
  61. };
  62. };
  63. }
  64. #endif