memory_resource.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //===------------------------ memory_resource.cpp -------------------------===//
  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. #include "experimental/memory_resource"
  10. #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
  11. #include "atomic"
  12. #elif !defined(_LIBCPP_HAS_NO_THREADS)
  13. #include "mutex"
  14. #endif
  15. _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
  16. // memory_resource
  17. //memory_resource::~memory_resource() {}
  18. // new_delete_resource()
  19. class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp
  20. : public memory_resource
  21. {
  22. public:
  23. ~__new_delete_memory_resource_imp() = default;
  24. protected:
  25. virtual void* do_allocate(size_t __size, size_t __align)
  26. { return __allocate(__size); }
  27. virtual void do_deallocate(void * __p, size_t, size_t)
  28. { __deallocate(__p); }
  29. virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
  30. { return &__other == this; }
  31. };
  32. // null_memory_resource()
  33. class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp
  34. : public memory_resource
  35. {
  36. public:
  37. ~__null_memory_resource_imp() = default;
  38. protected:
  39. virtual void* do_allocate(size_t, size_t) {
  40. #ifndef _LIBCPP_NO_EXCEPTIONS
  41. throw std::bad_alloc();
  42. #else
  43. abort();
  44. #endif
  45. }
  46. virtual void do_deallocate(void *, size_t, size_t) {}
  47. virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
  48. { return &__other == this; }
  49. };
  50. namespace {
  51. union ResourceInitHelper {
  52. struct {
  53. __new_delete_memory_resource_imp new_delete_res;
  54. __null_memory_resource_imp null_res;
  55. } resources;
  56. char dummy;
  57. _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
  58. ~ResourceInitHelper() {}
  59. };
  60. // When compiled in C++14 this initialization should be a constant expression.
  61. // Only in C++11 is "init_priority" needed to ensure initialization order.
  62. ResourceInitHelper res_init __attribute__((init_priority (101)));
  63. } // end namespace
  64. memory_resource * new_delete_resource() _NOEXCEPT {
  65. return &res_init.resources.new_delete_res;
  66. }
  67. memory_resource * null_memory_resource() _NOEXCEPT {
  68. return &res_init.resources.null_res;
  69. }
  70. // default_memory_resource()
  71. static memory_resource *
  72. __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT
  73. {
  74. #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
  75. static atomic<memory_resource*> __res =
  76. ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
  77. if (set) {
  78. new_res = new_res ? new_res : new_delete_resource();
  79. // TODO: Can a weaker ordering be used?
  80. return _VSTD::atomic_exchange_explicit(
  81. &__res, new_res, memory_order::memory_order_acq_rel);
  82. }
  83. else {
  84. return _VSTD::atomic_load_explicit(
  85. &__res, memory_order::memory_order_acquire);
  86. }
  87. #elif !defined(_LIBCPP_HAS_NO_THREADS)
  88. static memory_resource * res = &res_init.resources.new_delete_res;
  89. static mutex res_lock;
  90. if (set) {
  91. new_res = new_res ? new_res : new_delete_resource();
  92. lock_guard<mutex> guard(res_lock);
  93. memory_resource * old_res = res;
  94. res = new_res;
  95. return old_res;
  96. } else {
  97. lock_guard<mutex> guard(res_lock);
  98. return res;
  99. }
  100. #else
  101. static memory_resource* res = &res_init.resources.new_delete_res;
  102. if (set) {
  103. new_res = new_res ? new_res : new_delete_resource();
  104. memory_resource * old_res = res;
  105. res = new_res;
  106. return old_res;
  107. } else {
  108. return res;
  109. }
  110. #endif
  111. }
  112. memory_resource * get_default_resource() _NOEXCEPT
  113. {
  114. return __default_memory_resource();
  115. }
  116. memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT
  117. {
  118. return __default_memory_resource(true, __new_res);
  119. }
  120. _LIBCPP_END_NAMESPACE_LFTS_PMR