test_memory_resource.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is dual licensed under the MIT and the University of Illinois Open
  6. // Source Licenses. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef SUPPORT_TEST_MEMORY_RESOURCE_HPP
  10. #define SUPPORT_TEST_MEMORY_RESOURCE_HPP
  11. #include <experimental/memory_resource>
  12. #include <experimental/utility>
  13. #include <memory>
  14. #include <type_traits>
  15. #include <cstddef>
  16. #include <cstdlib>
  17. #include <cstring>
  18. #include <cstdint>
  19. #include <cassert>
  20. #include "test_macros.h"
  21. #include "controlled_allocators.hpp"
  22. #include "uses_alloc_types.hpp"
  23. // FIXME: This is a hack to allow uses_allocator_types.hpp to work with
  24. // erased_type. However we can't define that behavior directly in the header
  25. // because it can't include <experimental/memory_resource>
  26. template <>
  27. struct TransformErasedTypeAlloc<std::experimental::erased_type> {
  28. using type = std::experimental::pmr::memory_resource*;
  29. };
  30. template <class ProviderT, int = 0>
  31. class TestResourceImp : public std::experimental::pmr::memory_resource
  32. {
  33. public:
  34. static int resource_alive;
  35. static int resource_constructed;
  36. static int resource_destructed;
  37. static void resetStatics() {
  38. assert(resource_alive == 0);
  39. resource_alive = 0;
  40. resource_constructed = 0;
  41. resource_destructed = 0;
  42. }
  43. using memory_resource = std::experimental::pmr::memory_resource;
  44. using Provider = ProviderT;
  45. int value;
  46. explicit TestResourceImp(int val = 0) : value(val) {
  47. ++resource_alive;
  48. ++resource_constructed;
  49. }
  50. ~TestResourceImp() noexcept {
  51. --resource_alive;
  52. ++resource_destructed;
  53. }
  54. void reset() { C.reset(); P.reset(); }
  55. AllocController& getController() { return C; }
  56. bool checkAlloc(void* p, std::size_t s, std::size_t a) const
  57. { return C.checkAlloc(p, s, a); }
  58. bool checkDealloc(void* p, std::size_t s, std::size_t a) const
  59. { return C.checkDealloc(p, s, a); }
  60. bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); }
  61. protected:
  62. virtual void * do_allocate(std::size_t s, std::size_t a) {
  63. if (C.throw_on_alloc) {
  64. #ifndef TEST_HAS_NO_EXCEPTIONS
  65. throw TestException{};
  66. #else
  67. assert(false);
  68. #endif
  69. }
  70. void* ret = P.allocate(s, a);
  71. C.countAlloc(ret, s, a);
  72. return ret;
  73. }
  74. virtual void do_deallocate(void * p, std::size_t s, std::size_t a) {
  75. C.countDealloc(p, s, a);
  76. P.deallocate(p, s, a);
  77. }
  78. virtual bool do_is_equal(memory_resource const & other) const noexcept {
  79. C.countIsEqual();
  80. TestResourceImp const * o = dynamic_cast<TestResourceImp const *>(&other);
  81. return o && o->value == value;
  82. }
  83. private:
  84. mutable AllocController C;
  85. mutable Provider P;
  86. DISALLOW_COPY(TestResourceImp);
  87. };
  88. template <class Provider, int N>
  89. int TestResourceImp<Provider, N>::resource_alive = 0;
  90. template <class Provider, int N>
  91. int TestResourceImp<Provider, N>::resource_constructed = 0;
  92. template <class Provider, int N>
  93. int TestResourceImp<Provider, N>::resource_destructed = 0;
  94. struct NullProvider {
  95. NullProvider() {}
  96. void* allocate(size_t, size_t) { return nullptr; }
  97. void deallocate(void*, size_t, size_t) {}
  98. void reset() {}
  99. private:
  100. DISALLOW_COPY(NullProvider);
  101. };
  102. struct NewDeleteProvider {
  103. NewDeleteProvider() {}
  104. void* allocate(size_t s, size_t) { return ::operator new(s); }
  105. void deallocate(void* p, size_t, size_t) { ::operator delete(p); }
  106. void reset() {}
  107. private:
  108. DISALLOW_COPY(NewDeleteProvider);
  109. };
  110. template <size_t Size = 4096 * 10> // 10 pages worth of memory.
  111. struct BufferProvider {
  112. char buffer[Size];
  113. void* next = &buffer;
  114. size_t space = Size;
  115. BufferProvider() {}
  116. void* allocate(size_t s, size_t a) {
  117. void* ret = std::align(s, a, next, space);
  118. if (ret == nullptr) {
  119. #ifndef TEST_HAS_NO_EXCEPTIONS
  120. throw std::bad_alloc();
  121. #else
  122. assert(false);
  123. #endif
  124. }
  125. return ret;
  126. }
  127. void deallocate(void*, size_t, size_t) {}
  128. void reset() {
  129. next = &buffer;
  130. space = Size;
  131. }
  132. private:
  133. DISALLOW_COPY(BufferProvider);
  134. };
  135. using NullResource = TestResourceImp<NullProvider, 0>;
  136. using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>;
  137. using TestResource = TestResourceImp<BufferProvider<>, 0>;
  138. using TestResource1 = TestResourceImp<BufferProvider<>, 1>;
  139. using TestResource2 = TestResourceImp<BufferProvider<>, 2>;
  140. #endif /* SUPPORT_TEST_MEMORY_RESOURCE_HPP */