You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

aligned_allocator.h 3.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #pragma once
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <memory>
  5. #include <type_traits>
  6. #include "megdnn/arch.h"
  7. #if defined(_MSC_VER) || defined(__MINGW32__)
  8. #include "malloc.h"
  9. #endif
  10. #if defined(__ANDROID__) || defined(ANDROID)
  11. #include "malloc.h"
  12. #define HAS_MEMALIGN
  13. #elif !defined(_MSC_VER) && !defined(__MINGW32__)
  14. #define HAS_POSIX_MEMALIGN
  15. #endif
  16. namespace ah {
  17. /**
  18. * @tparam _Tp Type of allocated object.
  19. * @tparam _align Alignment, in bytes.
  20. */
  21. template <typename _Tp, size_t _align, bool _Nothrow = true>
  22. class aligned_allocator : public std::allocator<_Tp> {
  23. public:
  24. typedef size_t size_type;
  25. typedef std::ptrdiff_t difference_type;
  26. typedef _Tp* pointer;
  27. typedef const _Tp* const_pointer;
  28. typedef _Tp& reference;
  29. typedef const _Tp& const_reference;
  30. typedef _Tp value_type;
  31. template <typename _Tp1>
  32. struct rebind {
  33. typedef aligned_allocator<_Tp1, _align> other;
  34. };
  35. typedef std::true_type propagate_on_container_move_assignment;
  36. aligned_allocator() MEGDNN_NOEXCEPT {}
  37. template <typename _Tp1>
  38. aligned_allocator(const aligned_allocator<_Tp1, _align>&) MEGDNN_NOEXCEPT {}
  39. ~aligned_allocator() MEGDNN_NOEXCEPT {}
  40. // NB: __n is permitted to be 0. The C++ standard says nothing
  41. // about what the return value is when __n == 0.
  42. pointer allocate(size_type __n, const void* = 0) {
  43. if (__n > this->max_size())
  44. megdnn_trap();
  45. #ifdef HAS_POSIX_MEMALIGN
  46. _Tp* result;
  47. if (posix_memalign(&(void*&)result, _align, __n * sizeof(_Tp)) != 0) {
  48. if (_Nothrow) {
  49. return nullptr;
  50. } else {
  51. megdnn_trap();
  52. }
  53. }
  54. return result;
  55. #elif defined(HAS_MEMALIGN)
  56. return (_Tp*)memalign(_align, __n * sizeof(_Tp));
  57. #elif defined(_MSC_VER) || defined(__MINGW32__)
  58. return (_Tp*)_aligned_malloc(__n * sizeof(_Tp), _align);
  59. #else
  60. #warning \
  61. "aligned allocator fallbacks to normal malloc; allocated address may be unaligned"
  62. return (_Tp*)malloc(__n * sizeof(_Tp));
  63. #endif
  64. }
  65. // __p is not permitted to be a null pointer.
  66. void deallocate(pointer __p, size_type) {
  67. #ifdef _MSC_VER
  68. _aligned_free((void*)__p);
  69. #else
  70. free((void*)__p);
  71. #endif
  72. }
  73. };
  74. template <typename _T1, typename _T2, size_t _A1, size_t _A2>
  75. inline bool operator==(
  76. const aligned_allocator<_T1, _A1>&, const aligned_allocator<_T2, _A2>&) {
  77. return true;
  78. }
  79. template <typename _T1, typename _T2, size_t _A1, size_t _A2>
  80. inline bool operator!=(
  81. const aligned_allocator<_T1, _A1>&, const aligned_allocator<_T2, _A2>&) {
  82. return false;
  83. }
  84. /// allocator<void> specialization.
  85. template <size_t _align>
  86. class aligned_allocator<void, _align> {
  87. public:
  88. typedef size_t size_type;
  89. typedef std::ptrdiff_t difference_type;
  90. typedef void* pointer;
  91. typedef const void* const_pointer;
  92. typedef void value_type;
  93. template <typename _Tp1>
  94. struct rebind {
  95. typedef aligned_allocator<_Tp1, _align> other;
  96. };
  97. typedef std::true_type propagate_on_container_move_assignment;
  98. };
  99. } // namespace ah
  100. // vim: syntax=cpp.doxygen