3 #include "../utility/aligned_malloc.h"
4 #include "../utility/alignment.h"
5 #include "../utility/empty_base.h"
6 #include "../utility/meta.h"
11 #include <type_traits>
40 template<
typename Alloc,
template<
typename>
typename Atomic>
44 static_assert(detail::has_no_value_type_v<Alloc>,
"Building on top of typed allocators is not allowed. Use allocators without a type");
49 Atomic<detail::get_size_type_t<Alloc>> UseCount;
51 template<
typename... Args,
52 typename = std::enable_if_t<
53 std::is_constructible_v<Alloc, Args...>>>
54 block(Args&&... alloc)
55 noexcept(std::is_nothrow_constructible_v<Alloc, Args...>) :
56 Allocator(std::forward<Args>(alloc)...),
63 template<
typename A = Alloc>
65 noexcept(std::is_nothrow_default_constructible_v<block>) :
71 template<
typename... Args,
72 typename = std::enable_if_t<
73 std::is_constructible_v<Alloc, Args...>>>
75 noexcept(std::is_nothrow_constructible_v<block, Args...>) :
79 m_Block(other.m_Block)
85 m_Block(other.m_Block)
87 other.m_Block =
nullptr;
96 noexcept(noexcept(decrement()))
100 m_Block = rhs.m_Block;
108 noexcept(noexcept(decrement()))
112 m_Block = rhs.m_Block;
114 rhs.m_Block =
nullptr;
120 noexcept(detail::has_nothrow_equal_v<Alloc>)
122 return m_Block == rhs.m_Block && m_Block->Allocator == rhs.m_Block->Allocator;
126 noexcept(detail::has_nothrow_not_equal_v<Alloc>)
128 return m_Block != rhs.m_Block || m_Block->Allocator != rhs.m_Block->Allocator;
131 #pragma region Allocation
133 noexcept(detail::has_nothrow_allocate_v<Alloc>)
135 return m_Block->Allocator.allocate(n);
139 noexcept(detail::has_nothrow_deallocate_v<Alloc>)
141 m_Block->Allocator.deallocate(p, n);
145 #pragma region Construction
146 template<
typename T,
typename... Args>
149 noexcept(detail::has_nothrow_construct_v<Alloc, T*, Args...>)
151 m_Block->Allocator.construct(p, std::forward<Args>(args)...);
155 typename std::enable_if<detail::has_destroy_v<Alloc, T*>,
void>::type
157 noexcept(detail::has_nothrow_destroy_v<Alloc, T*>)
159 m_Block->Allocator.destroy(p);
163 #pragma region Utility
164 template<
typename A = Alloc>
165 typename std::enable_if<detail::has_max_size_v<A>,
size_type>::type
169 return m_Block->Allocator.max_size();
172 template<
typename A = Alloc>
173 typename std::enable_if<detail::has_owns_v<A>,
bool>::type
175 noexcept(detail::has_nothrow_owns_v<A>)
177 return m_Block->Allocator.owns(p);
183 return m_Block->Allocator;
188 return m_Block->Allocator;
192 void increment() noexcept
194 if (!m_Block)
return;
196 m_Block->UseCount.fetch_add(1, std::memory_order_acq_rel);
200 noexcept(std::is_nothrow_destructible_v<Alloc>)
202 if (!m_Block)
return;
204 if (m_Block->UseCount.fetch_sub(1, std::memory_order_acq_rel) == 1)
notomic() noexcept=default
T fetch_add(T add, std::memory_order) noexcept
Definition: shared.h:26
notomic(const notomic &)=delete
T fetch_sub(T add, std::memory_order) noexcept
Definition: shared.h:31
notomic(notomic &&)=delete
shared() noexcept(std::is_nothrow_default_constructible_v< block >)
Definition: shared.h:64
bool operator!=(const shared &rhs) const noexcept(detail::has_nothrow_not_equal_v< Alloc >)
Definition: shared.h:125
std::enable_if< detail::has_owns_v< A >, bool >::type owns(void *p) const noexcept(detail::has_nothrow_owns_v< A >)
Definition: shared.h:174
std::enable_if< detail::has_destroy_v< Alloc, T * >, void >::type destroy(T *p) noexcept(detail::has_nothrow_destroy_v< Alloc, T * >)
Definition: shared.h:156
shared & operator=(shared &&rhs) noexcept(noexcept(decrement()))
Definition: shared.h:107
shared(shared &&other) noexcept
Definition: shared.h:84
Alloc & get_allocator() noexcept
Definition: shared.h:181
~shared()
Definition: shared.h:90
bool operator==(const shared &rhs) const noexcept(detail::has_nothrow_equal_v< Alloc >)
Definition: shared.h:119
std::enable_if< detail::has_construct_v< Alloc, T *, Args... >, void >::type construct(T *p, Args &&... args) noexcept(detail::has_nothrow_construct_v< Alloc, T *, Args... >)
Definition: shared.h:148
const Alloc & get_allocator() const noexcept
Definition: shared.h:186
void deallocate(void *p, size_t n) noexcept(detail::has_nothrow_deallocate_v< Alloc >)
Definition: shared.h:138
shared(const shared &other) noexcept
Definition: shared.h:78
void * allocate(size_t n) noexcept(detail::has_nothrow_allocate_v< Alloc >)
Definition: shared.h:132
detail::get_size_type_t< Alloc > size_type
Definition: shared.h:61
shared & operator=(const shared &rhs) noexcept(noexcept(decrement()))
Definition: shared.h:95
shared(Args &&... alloc) noexcept(std::is_nothrow_constructible_v< block, Args... >)
Constructor for forwarding any arguments to the underlying allocator.
Definition: shared.h:74
std::enable_if< detail::has_max_size_v< A >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< A >)
Definition: shared.h:166
#define KTL_EMPTY_BASE
Definition: empty_base.h:6
constexpr bool has_construct_v
Definition: meta.h:41
void aligned_delete(T *p) noexcept(noexcept(p->~T()))
Definition: aligned_malloc.h:99
typename get_size_type< Alloc, void >::type get_size_type_t
Definition: meta.h:31
constexpr size_t ALIGNMENT
Definition: alignment.h:7
T * aligned_new(size_t alignment, Args &&... args) noexcept(noexcept(T(std::declval< Args >()...)))
Definition: aligned_malloc.h:90
constexpr bool has_nothrow_max_size_v
Definition: meta.h:122
Definition: cascading.h:15