monotonic_resource.ipp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
  3. // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Official repository: https://github.com/boostorg/json
  9. //
  10. #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
  11. #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
  12. #include <boost/json/monotonic_resource.hpp>
  13. #include <boost/json/detail/align.hpp>
  14. #include <boost/json/detail/except.hpp>
  15. #include <memory>
  16. BOOST_JSON_NS_BEGIN
  17. struct alignas(detail::max_align_t)
  18. monotonic_resource::block : block_base
  19. {
  20. };
  21. constexpr
  22. std::size_t
  23. monotonic_resource::
  24. max_size()
  25. {
  26. return std::size_t(-1) - sizeof(block);
  27. }
  28. // lowest power of 2 greater than or equal to n
  29. std::size_t
  30. monotonic_resource::
  31. round_pow2(
  32. std::size_t n) noexcept
  33. {
  34. if(n & (n - 1))
  35. return next_pow2(n);
  36. return n;
  37. }
  38. // lowest power of 2 greater than n
  39. std::size_t
  40. monotonic_resource::
  41. next_pow2(
  42. std::size_t n) noexcept
  43. {
  44. std::size_t result = min_size_;
  45. while(result <= n)
  46. {
  47. if(result >= max_size() - result)
  48. {
  49. // overflow
  50. result = max_size();
  51. break;
  52. }
  53. result *= 2;
  54. }
  55. return result;
  56. }
  57. //----------------------------------------------------------
  58. monotonic_resource::
  59. ~monotonic_resource()
  60. {
  61. release();
  62. }
  63. monotonic_resource::
  64. monotonic_resource(
  65. std::size_t initial_size,
  66. storage_ptr upstream) noexcept
  67. : buffer_{
  68. nullptr, 0, 0, nullptr}
  69. , next_size_(round_pow2(initial_size))
  70. , upstream_(std::move(upstream))
  71. {
  72. }
  73. monotonic_resource::
  74. monotonic_resource(
  75. unsigned char* buffer,
  76. std::size_t size,
  77. storage_ptr upstream) noexcept
  78. : buffer_{
  79. buffer, size, size, nullptr}
  80. , next_size_(next_pow2(size))
  81. , upstream_(std::move(upstream))
  82. {
  83. }
  84. void
  85. monotonic_resource::
  86. release() noexcept
  87. {
  88. auto p = head_;
  89. while(p != &buffer_)
  90. {
  91. auto next = p->next;
  92. upstream_->deallocate(p, p->size);
  93. p = next;
  94. }
  95. buffer_.p = reinterpret_cast<
  96. unsigned char*>(buffer_.p) - (
  97. buffer_.size - buffer_.avail);
  98. buffer_.avail = buffer_.size;
  99. head_ = &buffer_;
  100. }
  101. void*
  102. monotonic_resource::
  103. do_allocate(
  104. std::size_t n,
  105. std::size_t align)
  106. {
  107. auto p = detail::align(
  108. align, n, head_->p, head_->avail);
  109. if(p)
  110. {
  111. head_->p = reinterpret_cast<
  112. unsigned char*>(p) + n;
  113. head_->avail -= n;
  114. return p;
  115. }
  116. if(next_size_ < n)
  117. next_size_ = round_pow2(n);
  118. auto b = ::new(upstream_->allocate(
  119. sizeof(block) + next_size_)) block;
  120. b->p = b + 1;
  121. b->avail = next_size_;
  122. b->size = next_size_;
  123. b->next = head_;
  124. head_ = b;
  125. next_size_ = next_pow2(next_size_);
  126. p = detail::align(
  127. align, n, head_->p, head_->avail);
  128. BOOST_ASSERT(p);
  129. head_->p = reinterpret_cast<
  130. unsigned char*>(p) + n;
  131. head_->avail -= n;
  132. return p;
  133. }
  134. void
  135. monotonic_resource::
  136. do_deallocate(
  137. void*,
  138. std::size_t,
  139. std::size_t)
  140. {
  141. // do nothing
  142. }
  143. bool
  144. monotonic_resource::
  145. do_is_equal(
  146. memory_resource const& mr) const noexcept
  147. {
  148. return this == &mr;
  149. }
  150. BOOST_JSON_NS_END
  151. #endif