monotonic_buffer_resource.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
  11. #define BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
  12. #if defined (_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include <boost/container/detail/config_begin.hpp>
  16. #include <boost/container/detail/workaround.hpp>
  17. #include <boost/container/detail/auto_link.hpp>
  18. #include <boost/container/container_fwd.hpp>
  19. #include <boost/container/pmr/memory_resource.hpp>
  20. #include <boost/container/detail/block_slist.hpp>
  21. #include <cstddef>
  22. namespace boost {
  23. namespace container {
  24. namespace pmr {
  25. //! A monotonic_buffer_resource is a special-purpose memory resource intended for
  26. //! very fast memory allocations in situations where memory is used to build up a
  27. //! few objects and then is released all at once when the memory resource object
  28. //! is destroyed. It has the following qualities:
  29. //!
  30. //! - A call to deallocate has no effect, thus the amount of memory consumed
  31. //! increases monotonically until the resource is destroyed.
  32. //!
  33. //! - The program can supply an initial buffer, which the allocator uses to satisfy
  34. //! memory requests.
  35. //!
  36. //! - When the initial buffer (if any) is exhausted, it obtains additional buffers
  37. //! from an upstream memory resource supplied at construction. Each additional
  38. //! buffer is larger than the previous one, following a geometric progression.
  39. //!
  40. //! - It is intended for access from one thread of control at a time. Specifically,
  41. //! calls to allocate and deallocate do not synchronize with one another.
  42. //!
  43. //! - It owns the allocated memory and frees it on destruction, even if deallocate has
  44. //! not been called for some of the allocated blocks.
  45. class BOOST_CONTAINER_DECL monotonic_buffer_resource
  46. : public memory_resource
  47. {
  48. block_slist m_memory_blocks;
  49. void * m_current_buffer;
  50. std::size_t m_current_buffer_size;
  51. std::size_t m_next_buffer_size;
  52. void * const m_initial_buffer;
  53. std::size_t const m_initial_buffer_size;
  54. /// @cond
  55. void increase_next_buffer();
  56. void increase_next_buffer_at_least_to(std::size_t minimum_size);
  57. void *allocate_from_current(std::size_t aligner, std::size_t bytes);
  58. /// @endcond
  59. public:
  60. //! The number of bytes that will be requested by the default in the first call
  61. //! to the upstream allocator
  62. //!
  63. //! <b>Note</b>: Non-standard extension.
  64. static const std::size_t initial_next_buffer_size = 32u*sizeof(void*);
  65. //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
  66. //!
  67. //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
  68. //! to get_default_resource() otherwise.
  69. //! Sets the internal `current_buffer` to `nullptr` and the internal `next_buffer_size` to an
  70. //! implementation-defined size.
  71. explicit monotonic_buffer_resource(memory_resource* upstream = 0) BOOST_NOEXCEPT;
  72. //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
  73. //! and `initial_size` shall be greater than zero.
  74. //!
  75. //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
  76. //! to get_default_resource() otherwise. Sets the internal `current_buffer` to `nullptr` and
  77. //! `next_buffer_size` to at least `initial_size`.
  78. explicit monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
  79. //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`,
  80. //! `buffer_size` shall be no larger than the number of bytes in buffer.
  81. //!
  82. //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
  83. //! to get_default_resource() otherwise. Sets the internal `current_buffer` to `buffer`,
  84. //! and `next_buffer_size` to `buffer_size` (but not less than an implementation-defined size),
  85. //! then increases `next_buffer_size` by an implementation-defined growth factor (which need not be integral).
  86. monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
  87. #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  88. monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
  89. monotonic_buffer_resource operator=(const monotonic_buffer_resource&) = delete;
  90. #else
  91. private:
  92. monotonic_buffer_resource (const monotonic_buffer_resource&);
  93. monotonic_buffer_resource operator=(const monotonic_buffer_resource&);
  94. public:
  95. #endif
  96. //! <b>Effects</b>: Calls
  97. //! `this->release()`.
  98. virtual ~monotonic_buffer_resource();
  99. //! <b>Effects</b>: `upstream_resource()->deallocate()` as necessary to release all allocated memory.
  100. //! [Note: memory is released back to `upstream_resource()` even if some blocks that were allocated
  101. //! from this have not been deallocated from this. - end note]
  102. void release() BOOST_NOEXCEPT;
  103. //! <b>Returns</b>: The value of
  104. //! the internal resource.
  105. memory_resource* upstream_resource() const BOOST_NOEXCEPT;
  106. //! <b>Returns</b>:
  107. //! The number of bytes of storage available for the specified alignment and
  108. //! the number of bytes wasted due to the requested alignment.
  109. //!
  110. //! <b>Note</b>: Non-standard extension.
  111. std::size_t remaining_storage(std::size_t alignment, std::size_t &wasted_due_to_alignment) const BOOST_NOEXCEPT;
  112. //! <b>Returns</b>:
  113. //! The number of bytes of storage available for the specified alignment.
  114. //!
  115. //! <b>Note</b>: Non-standard extension.
  116. std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
  117. //! <b>Returns</b>:
  118. //! The address pointing to the start of the current free storage.
  119. //!
  120. //! <b>Note</b>: Non-standard extension.
  121. const void *current_buffer() const BOOST_NOEXCEPT;
  122. //! <b>Returns</b>:
  123. //! The number of bytes that will be requested for the next buffer once the
  124. //! current one is exhausted.
  125. //!
  126. //! <b>Note</b>: Non-standard extension.
  127. std::size_t next_buffer_size() const BOOST_NOEXCEPT;
  128. protected:
  129. //! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`. The size
  130. //! and alignment of the allocated memory shall meet the requirements for a class derived
  131. //! from `memory_resource`.
  132. //!
  133. //! <b>Effects</b>: If the unused space in the internal `current_buffer` can fit a block with the specified
  134. //! bytes and alignment, then allocate the return block from the internal `current_buffer`; otherwise sets
  135. //! the internal `current_buffer` to `upstream_resource()->allocate(n, m)`, where `n` is not less than
  136. //! `max(bytes, next_buffer_size)` and `m` is not less than alignment, and increase
  137. //! `next_buffer_size` by an implementation-defined growth factor (which need not be integral),
  138. //! then allocate the return block from the newly-allocated internal `current_buffer`.
  139. //!
  140. //! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
  141. virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
  142. //! <b>Effects</b>: None
  143. //!
  144. //! <b>Throws</b>: Nothing
  145. //!
  146. //! <b>Remarks</b>: Memory used by this resource increases monotonically until its destruction.
  147. virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_NOEXCEPT;
  148. //! <b>Returns</b>:
  149. //! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
  150. virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
  151. };
  152. } //namespace pmr {
  153. } //namespace container {
  154. } //namespace boost {
  155. #include <boost/container/detail/config_end.hpp>
  156. #endif //BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP