bit::memory
aligned_block_allocator.hpp
1 /*****************************************************************************
2  * \file
3  * \brief This header contains the implementation of a block allocator that
4  * allocates aligned memory
5  *****************************************************************************/
6 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2018 Matthew Rodusek
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BIT_MEMORY_BLOCK_ALLOCATORS_ALIGNED_BLOCK_ALLOCATOR_HPP
31 #define BIT_MEMORY_BLOCK_ALLOCATORS_ALIGNED_BLOCK_ALLOCATOR_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "detail/enum_types.hpp" // block_align_t, block_size_t
38 #include "detail/cached_block_allocator.hpp" // cached_block_allocator
39 #include "detail/named_block_allocator.hpp" // detail::named_block_allocator
40 
41 #include "../utilities/allocator_info.hpp" // allocator_info
42 #include "../utilities/dynamic_size_type.hpp" // dynamic_size, etc
43 #include "../utilities/ebo_storage.hpp" // ebo_storage
44 #include "../utilities/macros.hpp" // BIT_MEMORY_UNLIKELY
45 #include "../utilities/memory_block.hpp" // memory_block
46 #include "../utilities/owner.hpp" // owner
47 #include "../utilities/pointer_utilities.hpp" // is_power_of_two
48 
49 #include "../policies/growth_multipliers/no_growth.hpp"
50 
51 // regions
52 #include "../regions/aligned_heap_memory.hpp" // aligned_malloc, aligned_free
53 
54 #include <type_traits> // std::true_type, std::false_type, etc
55 #include <cstddef> // std::size_t, std::max_align_t
56 #include <cassert> // assert
57 
58 namespace bit {
59  namespace memory {
60 
78  template<std::size_t DefaultBlockSize,
79  std::size_t BlockAlign,
80  typename GrowthMultiplier=no_growth_multiplier>
82  : ebo_storage<GrowthMultiplier>,
83  dynamic_size_type<0,DefaultBlockSize>,
84  dynamic_size_type<1,BlockAlign>
85  {
89 
90  static_assert( is_power_of_two(BlockAlign) || BlockAlign == dynamic_size,
91  "Alignment must be a power of two!" );
92 
93  //-----------------------------------------------------------------------
94  // Constructors / Allocators
95  //-----------------------------------------------------------------------
96  public:
97 
100  aligned_block_allocator() = default;
101 
106  template<std::size_t USize=DefaultBlockSize,
107  std::size_t UAlign=BlockAlign,
108  typename=std::enable_if_t<(USize!=dynamic_block_size) &&
109  (UAlign!=dynamic_block_alignment)>>
110  explicit aligned_block_allocator( GrowthMultiplier growth );
111 
117  template<std::size_t USize=DefaultBlockSize,
118  typename=std::enable_if_t<USize==dynamic_block_size>>
119  explicit aligned_block_allocator( block_size_t block_size,
120  GrowthMultiplier growth = GrowthMultiplier{} );
121 
127  template<std::size_t UAlign=BlockAlign,
128  typename=std::enable_if_t<UAlign==dynamic_block_alignment>>
129  explicit aligned_block_allocator( block_alignment_t block_alignment,
130  GrowthMultiplier growth = GrowthMultiplier{} );
131 
138  template<std::size_t USize=DefaultBlockSize,
139  std::size_t UAlign=BlockAlign,
140  typename=std::enable_if_t<(USize==dynamic_block_size) &&
141  (UAlign==dynamic_block_alignment)>>
142  aligned_block_allocator( block_size_t block_size,
143  block_alignment_t block_alignment,
144  GrowthMultiplier growth = GrowthMultiplier{} );
145 
150 
154  aligned_block_allocator( const aligned_block_allocator& other ) = default;
155 
156  //-----------------------------------------------------------------------
157 
163 
168  aligned_block_allocator& operator=( const aligned_block_allocator& other ) = default;
169 
170  //-----------------------------------------------------------------------
171  // Block Allocations
172  //-----------------------------------------------------------------------
173  public:
174 
179  owner<memory_block> allocate_block() noexcept;
180 
184  void deallocate_block( owner<memory_block> block ) noexcept;
185 
186  //-----------------------------------------------------------------------
187  // Observers
188  //-----------------------------------------------------------------------
189  public:
190 
194  std::size_t next_block_size() const noexcept;
195 
202  allocator_info info() const noexcept;
203  };
204 
205  //-------------------------------------------------------------------------
206  // Utilities
207  //-------------------------------------------------------------------------
208 
213  template<std::size_t DefaultBlockSize,std::size_t BlockAlign,typename GrowthMultiplier=no_growth_multiplier>
214  using cached_aligned_block_allocator
215  = detail::cached_block_allocator<aligned_block_allocator<DefaultBlockSize,BlockAlign,GrowthMultiplier>>;
216 
217  //-------------------------------------------------------------------------
218 
219  template<std::size_t DefaultBlockSize,std::size_t BlockAlign,typename GrowthMultiplier=no_growth_multiplier>
220  using named_aligned_block_allocator
221  = detail::named_block_allocator<aligned_block_allocator<DefaultBlockSize,BlockAlign,GrowthMultiplier>>;
222 
223  template<std::size_t DefaultBlockSize,std::size_t BlockAlign,typename GrowthMultiplier=no_growth_multiplier>
224  using named_cached_aligned_block_allocator
225  = detail::named_block_allocator<cached_aligned_block_allocator<DefaultBlockSize,BlockAlign,GrowthMultiplier>>;
226 
227  } // namespace memory
228 } // namespace bit
229 
230 #include "detail/aligned_block_allocator.inl"
231 
232 #endif /* BIT_MEMORY_BLOCK_ALLOCATORS_ALIGNED_BLOCK_ALLOCATOR_HPP */
This type is used as a compile-time constant for storing size values.
aligned_block_allocator & operator=(aligned_block_allocator &&other)=default
Move-assigns an aligned_block_allocator from another allocator.
std::size_t next_block_size() const noexcept
Queries the next block size expected from this allocator.
An allocator that allocates over-aligned memory.
owner< memory_block > allocate_block() noexcept
Allocates a memory_block of size block_size with alignment Align.
allocator_info info() const noexcept
Gets the info about this allocator.
aligned_block_allocator()=default
Constructs a aligned_block_allocator that will distribute blocks of the specified size...
void deallocate_block(owner< memory_block > block) noexcept
Deallocates a given memory_block.
This type is used to hold the generic information for a given allocator.
A utility class used for leveraging empty-base optimization for a generic sequence of types...
Definition: ebo_storage.hpp:62