└── stack_allocator.hpp /stack_allocator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2015 Charles Salvia 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #ifndef INCLUDE_STACK_ALLOCATOR_HPP 28 | #define INCLUDE_STACK_ALLOCATOR_HPP 29 | 30 | #include 31 | #include 32 | 33 | template > 34 | class stack_allocator 35 | { 36 | public: 37 | 38 | typedef typename std::allocator_traits::value_type value_type; 39 | typedef typename std::allocator_traits::pointer pointer; 40 | typedef typename std::allocator_traits::const_pointer const_pointer; 41 | typedef typename Allocator::reference reference; 42 | typedef typename Allocator::const_reference const_reference; 43 | typedef typename std::allocator_traits::size_type size_type; 44 | typedef typename std::allocator_traits::difference_type difference_type; 45 | 46 | typedef typename std::allocator_traits::const_void_pointer const_void_pointer; 47 | typedef Allocator allocator_type; 48 | 49 | public: 50 | 51 | explicit stack_allocator(const allocator_type& alloc = allocator_type()) 52 | : m_allocator(alloc), m_begin(nullptr), m_end(nullptr), m_stack_pointer(nullptr) 53 | { } 54 | 55 | explicit stack_allocator(pointer buffer, const allocator_type& alloc = allocator_type()) 56 | : m_allocator(alloc), m_begin(buffer), m_end(buffer + N), 57 | m_stack_pointer(buffer) 58 | { } 59 | 60 | template 61 | stack_allocator(const stack_allocator& other) 62 | : m_allocator(other.m_allocator), m_begin(other.m_begin), m_end(other.m_end), 63 | m_stack_pointer(other.m_stack_pointer) 64 | { } 65 | 66 | constexpr static size_type capacity() 67 | { 68 | return N; 69 | } 70 | 71 | pointer allocate(size_type n, const_void_pointer hint = const_void_pointer()) 72 | { 73 | if (n <= size_type(std::distance(m_stack_pointer, m_end))) 74 | { 75 | pointer result = m_stack_pointer; 76 | m_stack_pointer += n; 77 | return result; 78 | } 79 | 80 | return m_allocator.allocate(n, hint); 81 | } 82 | 83 | void deallocate(pointer p, size_type n) 84 | { 85 | if (pointer_to_internal_buffer(p)) 86 | { 87 | m_stack_pointer -= n; 88 | } 89 | else m_allocator.deallocate(p, n); 90 | } 91 | 92 | size_type max_size() const noexcept 93 | { 94 | return m_allocator.max_size(); 95 | } 96 | 97 | template 98 | void construct(U* p, Args&&... args) 99 | { 100 | m_allocator.construct(p, std::forward(args)...); 101 | } 102 | 103 | template 104 | void destroy(U* p) 105 | { 106 | m_allocator.destroy(p); 107 | } 108 | 109 | pointer address(reference x) const noexcept 110 | { 111 | if (pointer_to_internal_buffer(std::addressof(x))) 112 | { 113 | return std::addressof(x); 114 | } 115 | 116 | return m_allocator.address(x); 117 | } 118 | 119 | const_pointer address(const_reference x) const noexcept 120 | { 121 | if (pointer_to_internal_buffer(std::addressof(x))) 122 | { 123 | return std::addressof(x); 124 | } 125 | 126 | return m_allocator.address(x); 127 | } 128 | 129 | template 130 | struct rebind { typedef stack_allocator other; }; 131 | 132 | pointer buffer() const noexcept 133 | { 134 | return m_begin; 135 | } 136 | 137 | private: 138 | 139 | bool pointer_to_internal_buffer(const_pointer p) const 140 | { 141 | return (!(std::less()(p, m_begin)) && (std::less()(p, m_end))); 142 | } 143 | 144 | allocator_type m_allocator; 145 | pointer m_begin; 146 | pointer m_end; 147 | pointer m_stack_pointer; 148 | }; 149 | 150 | template 151 | bool operator == (const stack_allocator& lhs, 152 | const stack_allocator& rhs) noexcept 153 | { 154 | return lhs.buffer() == rhs.buffer(); 155 | } 156 | 157 | template 158 | bool operator != (const stack_allocator& lhs, 159 | const stack_allocator& rhs) noexcept 160 | { 161 | return !(lhs == rhs); 162 | } 163 | 164 | // -------- Specialization for void 165 | // 166 | template 167 | class stack_allocator 168 | { 169 | public: 170 | 171 | typedef std::size_t size_type; 172 | typedef std::ptrdiff_t difference_type; 173 | typedef void* pointer; 174 | typedef const void* const_pointer; 175 | typedef void value_type; 176 | 177 | constexpr pointer buffer() const noexcept 178 | { 179 | return nullptr; 180 | } 181 | 182 | template 183 | struct rebind 184 | { 185 | typedef stack_allocator::other> other; 186 | }; 187 | }; 188 | 189 | #endif 190 | 191 | --------------------------------------------------------------------------------