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

byte_alloc.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_MEMORY_BYTE_ALLOC_HPP
10 #define EAGINE_MEMORY_BYTE_ALLOC_HPP
11 
12 #include "../assert.hpp"
13 #include "../interface.hpp"
14 #include "../tribool.hpp"
15 #include "../types.hpp"
16 #include "block.hpp"
17 #include <cstdint>
18 
19 namespace eagine::memory {
20 
21 // byte_allocator
22 struct byte_allocator
23  : interface<byte_allocator>
24  , block_owner {
25  using value_type = byte;
26  using size_type = span_size_t;
27 
28  virtual auto duplicate() noexcept -> byte_allocator* = 0;
29 
30  virtual auto release() noexcept -> bool = 0;
31 
32  virtual auto equal(byte_allocator* a) const noexcept -> bool = 0;
33 
34  virtual auto max_size(size_type a) noexcept -> size_type = 0;
35 
36  virtual auto has_allocated(const owned_block& b, size_type a = 0) noexcept
37  -> tribool = 0;
38 
39  virtual auto allocate(size_type n, size_type a) noexcept -> owned_block = 0;
40 
41  virtual void deallocate(owned_block&& b, size_type a = 0) noexcept = 0;
42 
43  virtual auto
44  can_reallocate(const owned_block& b, size_type n, size_type a) noexcept
45  -> bool = 0;
46 
47  virtual auto reallocate(owned_block&& b, size_type n, size_type a) noexcept
48  -> owned_block = 0;
49 
50  void do_reallocate(owned_block& b, size_type n, size_type a) noexcept {
51  if(b.size() != n) {
52  if(can_reallocate(b, n, a)) {
53  b = reallocate(std::move(b), n, a);
54  } else {
55  deallocate(std::move(b), a);
56  b = allocate(n, a);
57  }
58  }
59  }
60 
61  virtual void eject_self() noexcept = 0;
62 };
63 
64 // byte_alloc_managed_policy
65 struct byte_alloc_managed_policy {
66  inline auto duplicate(byte_allocator* that) noexcept -> byte_allocator* {
67  return that;
68  }
69 
70  inline auto release(byte_allocator*) noexcept -> bool {
71  return false;
72  }
73 };
74 
75 // byte_alloc_ref_count_policy
76 class byte_alloc_ref_count_policy {
77 private:
78  span_size_t _ref_count{1};
79 
80 public:
81  byte_alloc_ref_count_policy(const byte_alloc_ref_count_policy&) = delete;
82 
83  auto operator=(const byte_alloc_ref_count_policy&) = delete;
84  auto operator=(byte_alloc_ref_count_policy&& tmp) = delete;
85 
86  byte_alloc_ref_count_policy() noexcept = default;
87 
88  byte_alloc_ref_count_policy(byte_alloc_ref_count_policy&& tmp) noexcept
89  : _ref_count(tmp._ref_count) {
90  tmp._ref_count = 0;
91  }
92 
93  ~byte_alloc_ref_count_policy() noexcept {
94  EAGINE_ASSERT(_ref_count == 0);
95  }
96 
97  auto duplicate(byte_allocator* that) noexcept -> byte_allocator* {
98  ++_ref_count;
99  return that;
100  }
101 
102  auto release(byte_allocator*) noexcept -> bool {
103  return (--_ref_count == 0);
104  }
105 };
106 
107 // default_byte_allocator_policy
108 using default_byte_allocator_policy = byte_alloc_ref_count_policy;
109 
110 // byte_allocator_impl
111 template <typename Policy, template <class...> class DerivedTpl, typename... Args>
112 class byte_allocator_impl : public byte_allocator {
113 private:
114  Policy _policy;
115 
116  using Derived = DerivedTpl<Args..., Policy>;
117 
118  auto derived() -> Derived& {
119  return *static_cast<Derived*>(this);
120  }
121 
122 public:
123  using size_type = span_size_t;
124 
125  byte_allocator_impl() = default;
126  byte_allocator_impl(byte_allocator_impl&&) noexcept(
127  std::is_nothrow_move_constructible_v<Policy>) = default;
128  byte_allocator_impl(const byte_allocator_impl&) = delete;
129 
130  auto operator=(byte_allocator_impl&&) noexcept(
131  std::is_nothrow_move_assignable_v<Policy>)
132  -> byte_allocator_impl& = default;
133  auto operator=(const byte_allocator_impl&) = delete;
134 
135  ~byte_allocator_impl() noexcept override = default;
136 
137  auto duplicate() noexcept -> byte_allocator* override {
138  return _policy.duplicate(this);
139  }
140 
141  auto release() noexcept -> bool override {
142  return _policy.release(this);
143  }
144 
145  auto can_reallocate(const owned_block&, size_type, size_type) noexcept
146  -> bool override {
147  return false;
148  }
149 
150  auto reallocate(owned_block&& b, size_type, size_type) noexcept
151  -> owned_block override {
152  return std::move(b);
153  }
154 
155  template <typename Final>
156  static auto accomodate_derived(Final& that) noexcept -> Final* {
157  owned_block ob =
158  that.allocate(span_size_of<Final>(), span_align_of<Final>());
159  auto* const result = new(ob.begin()) Final(std::move(that));
160  release_block(std::move(ob));
161  return result;
162  }
163 
164  template <typename Final>
165  static void eject_derived(Final& that) noexcept {
166  Final tmp = std::move(that);
167  tmp.deallocate(
168  acquire_block(as_bytes(cover_one(that))), span_align_of<Final>());
169  }
170 
171  auto accomodate_self() noexcept -> Derived* {
172  return accomodate_derived(derived());
173  }
174 
175  void eject_self() noexcept override {
176  eject_derived(derived());
177  }
178 };
179 
180 } // namespace eagine::memory
181 
182 #endif // EAGINE_MEMORY_BYTE_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
static constexpr auto as_bytes(basic_span< T, P, S > spn) noexcept -> basic_block< std::is_const_v< T >>
Converts a span into a basic_block.
Definition: block.hpp:39
unsigned char byte
Byte type alias.
Definition: types.hpp:24

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