OGLplus  (0.59.0) a C++ wrapper for rendering APIs

shared_alloc.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_MEMORY_SHARED_ALLOC_HPP
10 #define EAGINE_MEMORY_SHARED_ALLOC_HPP
11 
12 #include "../assert.hpp"
13 #include "../nothing.hpp"
14 #include "byte_alloc.hpp"
15 #include <new>
16 #include <type_traits>
17 #include <typeinfo>
18 #include <utility>
19 
20 namespace eagine::memory {
21 
22 // shared_byte_allocator
23 template <typename Base>
24 class basic_shared_byte_alloc : public Base {
25 public:
26  using value_type = byte;
27  using size_type = span_size_t;
28 
29  template <typename X>
30  static constexpr const bool is_compatible_v =
31  std::is_convertible_v<std::decay_t<X>*, byte_allocator*>;
32 
33  template <typename X, typename T = void>
34  using enable_if_compatible_t = std::enable_if_t<is_compatible_v<X>, T>;
35 
36  basic_shared_byte_alloc() noexcept
37  : basic_shared_byte_alloc(nullptr) {}
38 
39  basic_shared_byte_alloc(const basic_shared_byte_alloc& that) noexcept
40  : basic_shared_byte_alloc(that._copy()) {}
41 
42  basic_shared_byte_alloc(basic_shared_byte_alloc&& tmp) noexcept
43  : basic_shared_byte_alloc(tmp._release()) {}
44 
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))) {}
48 
49  auto operator=(basic_shared_byte_alloc&& that) noexcept -> auto& {
50  if(this != std::addressof(that)) {
51  _cleanup();
52  _pballoc = that._release();
53  }
54  return *this;
55  }
56 
57  // NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
58  auto operator=(const basic_shared_byte_alloc& that) noexcept -> auto& {
59  if(this != std::addressof(that)) {
60  _cleanup();
61  _pballoc = that._copy();
62  }
63  return *this;
64  }
65 
66  ~basic_shared_byte_alloc() noexcept {
67  _cleanup();
68  }
69 
70  explicit operator bool() const noexcept {
71  return _pballoc != nullptr;
72  }
73 
74  auto max_size(size_type a) const noexcept -> size_type {
75  return _pballoc ? _pballoc->max_size(a) : 0;
76  }
77 
78  auto has_allocated(const owned_block& b, size_type a) noexcept -> tribool {
79  return _pballoc ? _pballoc->has_allocated(b, a)
80  : bool(b) ? tribool{false} : tribool{indeterminate};
81  }
82 
83  auto allocate(size_type n, size_type a) noexcept -> owned_block {
84  return _pballoc ? _pballoc->allocate(n, a) : owned_block{};
85  }
86 
87  void deallocate(owned_block&& b, size_type a) noexcept {
88  if(_pballoc) {
89  _pballoc->deallocate(std::move(b), a);
90  }
91  }
92 
93  auto can_reallocate(const owned_block& b, size_type n, size_type a) noexcept
94  -> bool {
95  return _pballoc ? _pballoc->can_reallocate(b, n, a) : (n == b.size());
96  }
97 
98  auto reallocate(owned_block&& b, size_type n, size_type a) noexcept
99  -> owned_block {
100  if(_pballoc) {
101  return _pballoc->reallocate(std::move(b), n, a);
102  }
103  EAGINE_ASSERT(n == b.size());
104  return std::move(b);
105  }
106 
107  void do_reallocate(owned_block& b, size_type n, size_type a) noexcept {
108  if(_pballoc) {
109  return _pballoc->do_reallocate(b, n, a);
110  }
111  EAGINE_ASSERT(n == b.size());
112  }
113 
114  friend auto operator==(
115  const basic_shared_byte_alloc& a,
116  const basic_shared_byte_alloc& b) noexcept {
117  if((a._pballoc == nullptr) && (b._pballoc == nullptr)) {
118  return true;
119  } else if(a._pballoc) {
120  return a._pballoc->equal(b._pballoc);
121  }
122  return false;
123  }
124 
125  friend auto operator!=(
126  const basic_shared_byte_alloc& a,
127  const basic_shared_byte_alloc& b) noexcept {
128  return !(a == b);
129  }
130 
131  template <typename ByteAlloc>
132  auto as() -> ByteAlloc& {
133  auto* pa = dynamic_cast<ByteAlloc*>(_pballoc);
134  if(pa == nullptr) {
135  throw std::bad_cast();
136  }
137  return *pa;
138  }
139 
140 private:
141  byte_allocator* _pballoc{nullptr};
142 
143  template <typename X>
144  static auto _get_new(X&& that) noexcept
145  -> enable_if_compatible_t<X, byte_allocator*> {
146  try {
147  return that.accomodate_self();
148  } catch(std::bad_alloc&) {
149  }
150  return nullptr;
151  }
152 
153  void _cleanup() noexcept {
154  if(_pballoc) {
155  if(_pballoc->release()) {
156  _pballoc->eject_self();
157  }
158  }
159  }
160 
161  auto _release() noexcept -> byte_allocator* {
162  byte_allocator* result = _pballoc;
163  _pballoc = nullptr;
164  return result;
165  }
166 
167  auto _copy() const noexcept -> byte_allocator* {
168  return _pballoc ? _pballoc->duplicate() : nullptr;
169  }
170 
171  explicit basic_shared_byte_alloc(byte_allocator* pballoc) noexcept
172  : _pballoc{pballoc} {}
173 };
174 
175 using shared_byte_allocator = basic_shared_byte_alloc<nothing_t>;
176 
177 } // namespace eagine::memory
178 
179 #endif // EAGINE_MEMORY_SHARED_ALLOC_HPP
value_type
Value tree value element data type enumeration.
Definition: interface.hpp:27
std::ptrdiff_t span_size_t
Signed span size type used by eagine.
Definition: types.hpp:36
constexpr static const indeterminate_t indeterminate
Constant representing unspecified tribool value.
Definition: tribool.hpp:24
static constexpr auto operator!=(const valid_if< T, P1 > &v1, const valid_if< T, P2 > &v2) noexcept -> tribool
Non-equality comparison of two conditionally valid values.
Definition: decl.hpp:169
unsigned char byte
Byte type alias.
Definition: types.hpp:24
auto operator==(message_id l, static_message_id< ClassId, MethodId > r) noexcept
Equality comparison between message_id and static_message_id.
Definition: message_id.hpp:131

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).