KTL
Loading...
Searching...
No Matches
segragator.h
Go to the documentation of this file.
1#pragma once
2
3#include "../utility/empty_base.h"
4#include "../utility/meta.h"
5#include "../utility/source_location.h"
6#include "segragator_fwd.h"
7#include "type_allocator.h"
8
9#include <memory>
10#include <type_traits>
11
12namespace ktl
13{
20 template<size_t Threshold, typename P, typename F>
22 {
23 private:
24 static_assert(detail::has_no_value_type_v<P>, "Building on top of typed allocators is not allowed. Use allocators without a type");
25 static_assert(detail::has_no_value_type_v<F>, "Building on top of typed allocators is not allowed. Use allocators without a type");
26
27 public:
29
30 segragator() = default;
31
35 template<typename Primary,
36 typename = std::enable_if_t<std::is_constructible_v<P, Primary>>>
37 explicit segragator(Primary&& primary)
38 noexcept(std::is_nothrow_constructible_v<P, Primary> && std::is_nothrow_default_constructible_v<F>) :
39 m_Primary(std::forward<Primary>(primary)),
40 m_Fallback() {}
41
45 template<typename Primary, typename Fallback,
46 typename = std::enable_if_t<
47 std::is_constructible_v<P, Primary> &&
48 std::is_constructible_v<F, Fallback>>>
49 explicit segragator(Primary&& primary, Fallback&& fallback)
50 noexcept(std::is_nothrow_constructible_v<P, Primary> && std::is_nothrow_constructible_v<F, Fallback>) :
51 m_Primary(std::forward<Primary>(primary)),
52 m_Fallback(std::forward<Fallback>(fallback)) {}
53
57 template<typename... Args,
58 typename = std::enable_if_t<
59 std::is_constructible_v<P, Args...>>>
60 explicit segragator(std::tuple<Args...>&& primary)
61 noexcept(std::is_nothrow_constructible_v<P, Args...> && std::is_nothrow_default_constructible_v<F>) :
62 m_Primary(std::make_from_tuple<P>(std::forward<std::tuple<Args...>>(primary))),
63 m_Fallback() {}
64
68 template<typename... ArgsP, typename... ArgsF,
69 typename = std::enable_if_t<
70 std::is_constructible_v<P, ArgsP...> &&
71 std::is_constructible_v<F, ArgsF...>>>
72 explicit segragator(std::tuple<ArgsP...>&& primary, std::tuple<ArgsF...>&& fallback)
73 noexcept(std::is_nothrow_constructible_v<P, ArgsP...> && std::is_nothrow_constructible_v<F, ArgsF...>) :
74 m_Primary(std::make_from_tuple<P>(std::forward<std::tuple<ArgsP...>>(primary))),
75 m_Fallback(std::make_from_tuple<F>(std::forward<std::tuple<ArgsF...>>(fallback))) {}
76
77 segragator(const segragator&) = default;
78
79 segragator(segragator&&) = default;
80
81 segragator& operator=(const segragator&) = default;
82
84
85 bool operator==(const segragator& rhs) const
87 {
88 return m_Primary == rhs.m_Primary && m_Fallback == rhs.m_Fallback;
89 }
90
91 bool operator!=(const segragator& rhs) const
93 {
94 return m_Primary != rhs.m_Primary || m_Fallback != rhs.m_Fallback;
95 }
96
97#pragma region Allocation
98 void* allocate(size_t n, const source_location source = KTL_SOURCE())
99 noexcept(detail::has_nothrow_allocate_v<P> && detail::has_nothrow_allocate_v<F>)
100 {
101 if (n <= Threshold)
102 return detail::allocate(m_Primary, n, source);
103 else
104 return detail::allocate(m_Fallback, n, source);
105 }
106
107 void deallocate(void* p, size_t n)
109 {
110 if (n <= Threshold)
111 return m_Primary.deallocate(p, n);
112 else
113 return m_Fallback.deallocate(p, n);
114 }
115#pragma endregion
116
117#pragma region Construction
118 template<typename T, typename... Args>
119 typename std::enable_if<detail::has_construct_v<P, T*, Args...> || detail::has_construct_v<F, T*, Args...>, void>::type
120 construct(T* p, Args&&... args) noexcept(
121 (!detail::has_construct_v<P, T*, Args...> || detail::has_nothrow_construct_v<P, T*, Args...>) &&
123 std::is_nothrow_constructible_v<T, Args...>)
124 {
125 bool owned = m_Primary.owns(p);
126
127 if constexpr (detail::has_construct_v<P, T*, Args...>)
128 {
129 if (owned)
130 {
131 m_Primary.construct(p, std::forward<Args>(args)...);
132 return;
133 }
134 }
135
136 if constexpr (detail::has_construct_v<F, T*, Args...>)
137 {
138 if (!owned)
139 {
140 m_Fallback.construct(p, std::forward<Args>(args)...);
141 return;
142 }
143 }
144
145 ::new(p) T(std::forward<Args>(args)...);
146 }
147
148 template<typename T>
149 typename std::enable_if<detail::has_destroy_v<P, T*> || detail::has_destroy_v<F, T*>, void>::type
150 destroy(T* p) noexcept(
153 std::is_nothrow_destructible_v<T>)
154 {
155 bool owned = m_Primary.owns(p);
156
157 if constexpr (detail::has_destroy_v<P, T*>)
158 {
159 if (owned)
160 {
161 m_Primary.destroy(p);
162 return;
163 }
164 }
165
166 if constexpr (detail::has_destroy_v<F, T*>)
167 {
168 if (!owned)
169 {
170 m_Fallback.destroy(p);
171 return;
172 }
173 }
174
175 p->~T();
176 }
177#pragma endregion
178
179#pragma region Utility
180 template<typename Primary = P, typename Fallback = F>
181 typename std::enable_if<detail::has_max_size_v<Primary> && detail::has_max_size_v<Fallback>, size_type>::type
182 max_size() const
183 noexcept(detail::has_nothrow_max_size_v<Primary> && detail::has_nothrow_max_size_v<Fallback>)
184 {
185 return (std::max)(m_Primary.max_size(), m_Fallback.max_size());
186 }
187
188 template<typename Primary = P, typename Fallback = F>
189 typename std::enable_if<detail::has_owns_v<Primary> && detail::has_owns_v<Fallback>, bool>::type
190 owns(void* p) const
192 {
193 if (m_Primary.owns(p))
194 return true;
195
196 return m_Fallback.owns(p);
197 }
198#pragma endregion
199
200 private:
201 KTL_EMPTY_BASE P m_Primary;
202 KTL_EMPTY_BASE F m_Fallback;
203 };
204}
An allocator which delegates allocations between 2 different allocators. It first attempts to allocat...
Definition fallback.h:24
An allocator which delegates allocations between 2 different allocators based on a size threshold.
Definition segragator.h:22
segragator(Primary &&primary, Fallback &&fallback) noexcept(std::is_nothrow_constructible_v< P, Primary > &&std::is_nothrow_constructible_v< F, Fallback >)
Constructor for forwarding a single argument to the primary and fallback allocators.
Definition segragator.h:49
std::enable_if< detail::has_construct_v< P, T *, Args... >||detail::has_construct_v< F, T *, Args... >, void >::type construct(T *p, Args &&... args) noexcept((!detail::has_construct_v< P, T *, Args... >||detail::has_nothrow_construct_v< P, T *, Args... >) &&(!detail::has_construct_v< F, T *, Args... >||detail::has_nothrow_construct_v< F, T *, Args... >) &&std::is_nothrow_constructible_v< T, Args... >)
Definition segragator.h:120
bool operator!=(const segragator &rhs) const noexcept(detail::has_nothrow_not_equal_v< P > &&detail::has_nothrow_not_equal_v< F >)
Definition segragator.h:91
segragator(segragator &&)=default
std::enable_if< detail::has_owns_v< Primary > &&detail::has_owns_v< Fallback >, bool >::type owns(void *p) const noexcept(detail::has_nothrow_owns_v< Primary > &&detail::has_nothrow_owns_v< Fallback >)
Definition segragator.h:190
detail::get_size_type_t< P > size_type
Definition segragator.h:28
segragator & operator=(const segragator &)=default
segragator(std::tuple< Args... > &&primary) noexcept(std::is_nothrow_constructible_v< P, Args... > &&std::is_nothrow_default_constructible_v< F >)
Constructor for forwarding a tuple of arguments to the primary allocator.
Definition segragator.h:60
segragator(const segragator &)=default
std::enable_if< detail::has_destroy_v< P, T * >||detail::has_destroy_v< F, T * >, void >::type destroy(T *p) noexcept((!detail::has_destroy_v< P, T * >||detail::has_nothrow_destroy_v< P, T * >) &&(!detail::has_destroy_v< F, T * >||detail::has_nothrow_destroy_v< F, T * >) &&std::is_nothrow_destructible_v< T >)
Definition segragator.h:150
void * allocate(size_t n, const source_location source=KTL_SOURCE()) noexcept(detail::has_nothrow_allocate_v< P > &&detail::has_nothrow_allocate_v< F >)
Definition segragator.h:98
std::enable_if< detail::has_max_size_v< Primary > &&detail::has_max_size_v< Fallback >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< Primary > &&detail::has_nothrow_max_size_v< Fallback >)
Definition segragator.h:182
segragator()=default
bool operator==(const segragator &rhs) const noexcept(detail::has_nothrow_equal_v< P > &&detail::has_nothrow_equal_v< F >)
Definition segragator.h:85
segragator(std::tuple< ArgsP... > &&primary, std::tuple< ArgsF... > &&fallback) noexcept(std::is_nothrow_constructible_v< P, ArgsP... > &&std::is_nothrow_constructible_v< F, ArgsF... >)
Constructor for forwarding a tuple of arguments to the primary and fallback allocators.
Definition segragator.h:72
segragator(Primary &&primary) noexcept(std::is_nothrow_constructible_v< P, Primary > &&std::is_nothrow_default_constructible_v< F >)
Constructor for forwarding a single argument to the primary allocator.
Definition segragator.h:37
segragator & operator=(segragator &&)=default
void deallocate(void *p, size_t n) noexcept(detail::has_nothrow_deallocate_v< P > &&detail::has_nothrow_deallocate_v< F >)
Definition segragator.h:107
#define KTL_EMPTY_BASE
Definition empty_base.h:6
typename get_size_type< Alloc, void >::type get_size_type_t
Definition meta.h:33
constexpr bool has_nothrow_construct_v
Definition meta.h:123
constexpr bool has_construct_v
Definition meta.h:53
void * allocate(Alloc &alloc, size_t n, const source_location source) noexcept(false)
Definition meta.h:161
constexpr bool has_no_value_type_v
Definition meta.h:17
Definition cascading.h:16
#define KTL_SOURCE()
Definition source_location.h:11
Definition source_location.h:19