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