greenlet_allocator.hpp 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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. namespace greenlet
  8. {
  9. // This allocator is stateless; all instances are identical.
  10. // It can *ONLY* be used when we're sure we're holding the GIL
  11. // (Python's allocators require the GIL).
  12. template <class T>
  13. struct PythonAllocator : public std::allocator<T> {
  14. PythonAllocator(const PythonAllocator& UNUSED(other))
  15. : std::allocator<T>()
  16. {
  17. }
  18. PythonAllocator(const std::allocator<T> other)
  19. : std::allocator<T>(other)
  20. {}
  21. template <class U>
  22. PythonAllocator(const std::allocator<U>& other)
  23. : std::allocator<T>(other)
  24. {
  25. }
  26. PythonAllocator() : std::allocator<T>() {}
  27. T* allocate(size_t number_objects, const void* UNUSED(hint)=0)
  28. {
  29. void* p;
  30. if (number_objects == 1)
  31. p = PyObject_Malloc(sizeof(T));
  32. else
  33. p = PyMem_Malloc(sizeof(T) * number_objects);
  34. return static_cast<T*>(p);
  35. }
  36. void deallocate(T* t, size_t n)
  37. {
  38. void* p = t;
  39. if (n == 1) {
  40. PyObject_Free(p);
  41. }
  42. else
  43. PyMem_Free(p);
  44. }
  45. // This member is deprecated in C++17 and removed in C++20
  46. template< class U >
  47. struct rebind {
  48. typedef PythonAllocator<U> other;
  49. };
  50. };
  51. }
  52. #endif