bit::memory
fallback_allocator.hpp
1 /*****************************************************************************
2  * \file
3  * \brief This header defines an allocator that falls-back on failure to other
4  * allocators
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_ALLOCATORS_FALLBACK_ALLOCATOR_HPP
31 #define BIT_MEMORY_ALLOCATORS_FALLBACK_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/named_allocator.hpp" // detail::named_allocator
38 
39 #include "../utilities/ebo_storage.hpp" // detail::ebo_storage
40 #include "../utilities/macros.hpp" // BIT_MEMORY_UNUSED
41 #include "../utilities/owner.hpp" // owner
42 
43 #include "../concepts/Allocator.hpp" // allocator_pointer_t, etc
44 
45 #include "../traits/allocator_traits.hpp" // allocator_traits
46 
47 #include <tuple> // std::forward_as_tuple
48 #include <utility> // std::forward
49 #include <cstddef> // std::size_t
50 #include <algorithm> // std::max, std::min
51 
52 namespace bit {
53  namespace memory {
54 
72  template<typename...AllocatorStorages>
74  : private ebo_storage<AllocatorStorages...>
75  {
76 
77  using base_type = ebo_storage<AllocatorStorages...>;
78 
79  // TODO(bitwizeshift): Support pretty-pointers by determining the common
80  // 'pointer', 'const_pointer', and 'size_type' of
81  // each allocator
82 
83  //-----------------------------------------------------------------------
84  // Constructors
85  //-----------------------------------------------------------------------
86  public:
87 
92  explicit fallback_allocator( AllocatorStorages...storages ) noexcept;
93 
100  fallback_allocator( fallback_allocator&& other ) = default;
101 
108  fallback_allocator( const fallback_allocator& other ) = default;
109 
110  //-----------------------------------------------------------------------
111 
118  fallback_allocator& operator=( fallback_allocator&& other ) = default;
119 
126  fallback_allocator& operator=( const fallback_allocator& other ) = default;
127 
128  //-----------------------------------------------------------------------
129  // Allocations
130  //-----------------------------------------------------------------------
131  public:
132 
139  owner<void*> try_allocate( std::size_t size,
140  std::size_t align ) noexcept;
141 
152  void deallocate( owner<void*> p, std::size_t size );
153 
154  //-----------------------------------------------------------------------
155  // Observers
156  //-----------------------------------------------------------------------
157  public:
158 
164  bool owns( const void* p ) const noexcept;
165 
166  //-----------------------------------------------------------------------
167  // Capacity
168  //-----------------------------------------------------------------------
169  public:
170 
175  std::size_t max_size() const noexcept;
176 
181  std::size_t min_size() const noexcept;
182 
183  //-----------------------------------------------------------------------
184  // Private Allocation / Deallocation
185  //-----------------------------------------------------------------------
186  private:
187 
188  template<std::size_t Idx>
189  void* do_try_allocate( std::integral_constant<std::size_t,Idx>,
190  std::size_t size,
191  std::size_t align ) noexcept;
192 
193  void* do_try_allocate( std::integral_constant<std::size_t,sizeof...(AllocatorStorages)-1>,
194  std::size_t size,
195  std::size_t align ) noexcept;
196 
197  //-----------------------------------------------------------------------
198 
199  template<std::size_t Idx>
200  void do_deallocate( std::integral_constant<std::size_t,Idx>,
201  void* p,
202  std::size_t size );
203 
204  void do_deallocate( std::integral_constant<std::size_t,sizeof...(AllocatorStorages)-1>,
205  void* p,
206  std::size_t size );
207 
208  //-----------------------------------------------------------------------
209  // Private Observers
210  //-----------------------------------------------------------------------
211  private:
212 
213  template<std::size_t...Idxs>
214  bool do_owns( std::index_sequence<Idxs...>,
215  const void* p ) const noexcept;
216 
217  //-----------------------------------------------------------------------
218  // Private Capacity
219  //-----------------------------------------------------------------------
220  private:
221 
222  template<std::size_t...Idxs>
223  std::size_t do_max_size( std::index_sequence<Idxs...> ) const noexcept;
224 
225  template<std::size_t...Idxs>
226  std::size_t do_min_size( std::index_sequence<Idxs...> ) const noexcept;
227 
228  };
229 
230  //-------------------------------------------------------------------------
231  // Utilities
232  //-------------------------------------------------------------------------
233 
234  template<typename...Allocators>
235  using named_fallback_allocator = detail::named_allocator<fallback_allocator<Allocators...>>;
236 
237  //-------------------------------------------------------------------------
238 
245  template<typename...AllocatorStorages>
246  fallback_allocator<AllocatorStorages...>
247  make_fallback_allocator( AllocatorStorages...storages );
248 
256  template<typename...AllocatorStorages>
257  named_fallback_allocator<AllocatorStorages...>
258  make_named_fallback_allocator( const char* name,
259  AllocatorStorages...storages );
260 
261  } // namespace memory
262 } // namespace bit
263 
264 #include "detail/fallback_allocator.inl"
265 
266 #endif /* BIT_MEMORY_ALLOCATORS_FALLBACK_ALLOCATOR_HPP */
owner< void * > try_allocate(std::size_t size, std::size_t align) noexcept
Attempts to allocate memory, starting with the first allocator in sequence, and falling back to furth...
fallback_allocator(AllocatorStorages...storages) noexcept
Constructs each allocator in the fallback_allocator in-place, constructing each allocator from a sing...
fallback_allocator & operator=(fallback_allocator &&other)=default
Move-assigns the fallback_allocator from an existing one.
std::size_t max_size() const noexcept
Determines the maximum size of the allocations that this fallback_allocator supports.
bool owns(const void *p) const noexcept
Checks if any of the allocators in the fallback allocator owns the memory pointer to by p...
void deallocate(owner< void *> p, std::size_t size)
Deallocates the pointer p of size size from the underlying allocator.
This allocator acts as an aggregate that can fall back to other allocators on failure.
std::size_t min_size() const noexcept
Determines the minimum size of the allocations that this fallback_allocator supports.
A utility class used for leveraging empty-base optimization for a generic sequence of types...
Definition: ebo_storage.hpp:62