monotonic_resource.ipp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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/except.hpp>
  14. #include <boost/align/align.hpp>
  15. #include <boost/core/max_align.hpp>
  16. #include <memory>
  17. namespace boost {
  18. namespace json {
  19. struct alignas(core::max_align_t)
  20. monotonic_resource::block : block_base
  21. {
  22. };
  23. constexpr
  24. std::size_t
  25. monotonic_resource::
  26. max_size()
  27. {
  28. return std::size_t(-1) - sizeof(block);
  29. }
  30. // lowest power of 2 greater than or equal to n
  31. std::size_t
  32. monotonic_resource::
  33. round_pow2(
  34. std::size_t n) noexcept
  35. {
  36. if(n & (n - 1))
  37. return next_pow2(n);
  38. return n;
  39. }
  40. // lowest power of 2 greater than n
  41. std::size_t
  42. monotonic_resource::
  43. next_pow2(
  44. std::size_t n) noexcept
  45. {
  46. std::size_t result = min_size_;
  47. while(result <= n)
  48. {
  49. if(result >= max_size() - result)
  50. {
  51. // overflow
  52. result = max_size();
  53. break;
  54. }
  55. result *= 2;
  56. }
  57. return result;
  58. }
  59. //----------------------------------------------------------
  60. monotonic_resource::
  61. ~monotonic_resource()
  62. {
  63. release();
  64. }
  65. monotonic_resource::
  66. monotonic_resource(
  67. std::size_t initial_size,
  68. storage_ptr upstream) noexcept
  69. : buffer_{
  70. nullptr, 0, 0, nullptr}
  71. , next_size_(round_pow2(initial_size))
  72. , upstream_(std::move(upstream))
  73. {
  74. }
  75. monotonic_resource::
  76. monotonic_resource(
  77. unsigned char* buffer,
  78. std::size_t size,
  79. storage_ptr upstream) noexcept
  80. : buffer_{
  81. buffer, size, size, nullptr}
  82. , next_size_(next_pow2(size))
  83. , upstream_(std::move(upstream))
  84. {
  85. }
  86. void
  87. monotonic_resource::
  88. release() noexcept
  89. {
  90. auto p = head_;
  91. while(p != &buffer_)
  92. {
  93. auto next = p->next;
  94. upstream_->deallocate(p, p->size);
  95. p = next;
  96. }
  97. buffer_.p = reinterpret_cast<
  98. unsigned char*>(buffer_.p) - (
  99. buffer_.size - buffer_.avail);
  100. buffer_.avail = buffer_.size;
  101. head_ = &buffer_;
  102. }
  103. void*
  104. monotonic_resource::
  105. do_allocate(
  106. std::size_t n,
  107. std::size_t align)
  108. {
  109. auto p = alignment::align(
  110. align, n, head_->p, head_->avail);
  111. if(p)
  112. {
  113. head_->p = reinterpret_cast<
  114. unsigned char*>(p) + n;
  115. head_->avail -= n;
  116. return p;
  117. }
  118. if(next_size_ < n)
  119. next_size_ = round_pow2(n);
  120. auto b = ::new(upstream_->allocate(
  121. sizeof(block) + next_size_)) block;
  122. b->p = b + 1;
  123. b->avail = next_size_;
  124. b->size = next_size_;
  125. b->next = head_;
  126. head_ = b;
  127. next_size_ = next_pow2(next_size_);
  128. p = alignment::align(
  129. align, n, head_->p, head_->avail);
  130. BOOST_ASSERT(p);
  131. head_->p = reinterpret_cast<
  132. unsigned char*>(p) + n;
  133. head_->avail -= n;
  134. return p;
  135. }
  136. void
  137. monotonic_resource::
  138. do_deallocate(
  139. void*,
  140. std::size_t,
  141. std::size_t)
  142. {
  143. // do nothing
  144. }
  145. bool
  146. monotonic_resource::
  147. do_is_equal(
  148. memory_resource const& mr) const noexcept
  149. {
  150. return this == &mr;
  151. }
  152. } // namespace json
  153. } // namespace boost
  154. #endif