9 #ifndef EAGINE_MEMORY_SHARED_ALLOC_HPP
10 #define EAGINE_MEMORY_SHARED_ALLOC_HPP
12 #include "../assert.hpp"
13 #include "../nothing.hpp"
16 #include <type_traits>
20 namespace eagine::memory {
23 template <
typename Base>
24 class basic_shared_byte_alloc :
public Base {
30 static constexpr
const bool is_compatible_v =
31 std::is_convertible_v<std::decay_t<X>*, byte_allocator*>;
33 template <
typename X,
typename T =
void>
34 using enable_if_compatible_t = std::enable_if_t<is_compatible_v<X>, T>;
36 basic_shared_byte_alloc() noexcept
37 : basic_shared_byte_alloc(
nullptr) {}
39 basic_shared_byte_alloc(
const basic_shared_byte_alloc& that) noexcept
40 : basic_shared_byte_alloc(that._copy()) {}
42 basic_shared_byte_alloc(basic_shared_byte_alloc&& tmp) noexcept
43 : basic_shared_byte_alloc(tmp._release()) {}
45 template <
typename X,
typename = enable_if_compatible_t<X>>
46 basic_shared_byte_alloc(X&& x) noexcept
47 : basic_shared_byte_alloc(_get_new(std::forward<X>(x))) {}
49 auto operator=(basic_shared_byte_alloc&& that) noexcept ->
auto& {
50 if(
this != std::addressof(that)) {
52 _pballoc = that._release();
58 auto operator=(
const basic_shared_byte_alloc& that) noexcept ->
auto& {
59 if(
this != std::addressof(that)) {
61 _pballoc = that._copy();
66 ~basic_shared_byte_alloc() noexcept {
70 explicit operator bool() const noexcept {
71 return _pballoc !=
nullptr;
74 auto max_size(size_type a)
const noexcept -> size_type {
75 return _pballoc ? _pballoc->max_size(a) : 0;
78 auto has_allocated(
const owned_block& b, size_type a) noexcept -> tribool {
79 return _pballoc ? _pballoc->has_allocated(b, a)
83 auto allocate(size_type n, size_type a) noexcept -> owned_block {
84 return _pballoc ? _pballoc->allocate(n, a) : owned_block{};
87 void deallocate(owned_block&& b, size_type a) noexcept {
89 _pballoc->deallocate(std::move(b), a);
93 auto can_reallocate(
const owned_block& b, size_type n, size_type a) noexcept
95 return _pballoc ? _pballoc->can_reallocate(b, n, a) : (n == b.size());
98 auto reallocate(owned_block&& b, size_type n, size_type a) noexcept
101 return _pballoc->reallocate(std::move(b), n, a);
103 EAGINE_ASSERT(n == b.size());
107 void do_reallocate(owned_block& b, size_type n, size_type a) noexcept {
109 return _pballoc->do_reallocate(b, n, a);
111 EAGINE_ASSERT(n == b.size());
115 const basic_shared_byte_alloc& a,
116 const basic_shared_byte_alloc& b) noexcept {
117 if((a._pballoc ==
nullptr) && (b._pballoc ==
nullptr)) {
119 }
else if(a._pballoc) {
120 return a._pballoc->equal(b._pballoc);
126 const basic_shared_byte_alloc& a,
127 const basic_shared_byte_alloc& b) noexcept {
131 template <
typename ByteAlloc>
132 auto as() -> ByteAlloc& {
133 auto* pa =
dynamic_cast<ByteAlloc*
>(_pballoc);
135 throw std::bad_cast();
141 byte_allocator* _pballoc{
nullptr};
143 template <
typename X>
144 static auto _get_new(X&& that) noexcept
145 -> enable_if_compatible_t<X, byte_allocator*> {
147 return that.accomodate_self();
148 }
catch(std::bad_alloc&) {
153 void _cleanup() noexcept {
155 if(_pballoc->release()) {
156 _pballoc->eject_self();
161 auto _release() noexcept -> byte_allocator* {
162 byte_allocator* result = _pballoc;
167 auto _copy() const noexcept -> byte_allocator* {
168 return _pballoc ? _pballoc->duplicate() :
nullptr;
171 explicit basic_shared_byte_alloc(byte_allocator* pballoc) noexcept
172 : _pballoc{pballoc} {}
175 using shared_byte_allocator = basic_shared_byte_alloc<nothing_t>;
179 #endif // EAGINE_MEMORY_SHARED_ALLOC_HPP