libER 0.1.4.2
ELDEN RING API library
Loading...
Searching...
No Matches
utility.hpp
Go to the documentation of this file.
1
8#pragma once
9
10#include <detail/preprocessor.hpp>
12
13#include <algorithm>
14#include <atomic>
15#include <compare>
16#include <concepts>
17#include <stdexcept>
18#include <utility>
19
20namespace from {
21// Dantelion2 utility
22namespace DLUT {
28public:
29 DLNonCopyable() = default;
30 LIBERAPI virtual ~DLNonCopyable();
31
32 DLNonCopyable(const DLNonCopyable&) = delete;
33 DLNonCopyable& operator=(const DLNonCopyable&) = delete;
34};
35
48public:
49 LIBER_CLASS(DLReferenceCountObject);
50
55 virtual void deleter() {
57 get_allocator_of(this).deallocate(this);
58 }
59
60 virtual ~DLReferenceCountObject() = default;
61
67 int count() const noexcept {
68 return this->counter.load(std::memory_order_relaxed);
69 }
70
75 void ref() noexcept {
76 ++this->counter;
77 }
78
86 void unref() {
87 int value = this->counter.fetch_add(-1, std::memory_order_seq_cst);
88 if (value == 1)
89 this->deleter();
90 else if (value < 1)
91 throw std::runtime_error("bad unref() call");
92 }
93
94protected:
102 DLReferenceCountObject() noexcept = default;
103
104private:
105 template <typename T, typename... Args>
106 requires std::derived_from<T, DLReferenceCountObject>
107 friend inline auto make_refcounted();
108
109 std::atomic_int counter = 0;
110};
111
112// A refcounted pointer that models std::shared_ptr
113// Use from::make_refcounted<T>(...) to create refcounted objects
114// These objects must derive from DLReferenceCountObject
124template <typename T>
125 requires std::derived_from<T, DLReferenceCountObject>
127public:
128 LIBER_CLASS(DLReferenceCountPtr);
129
130 DLReferenceCountPtr() noexcept : raw(nullptr) {}
131
136 DLReferenceCountPtr(std::nullptr_t) noexcept : raw(nullptr) {}
137
145 template <class U>
146 requires std::convertible_to<U*, T*>
147 explicit DLReferenceCountPtr(U* raw) noexcept : raw(raw) {
148 if (this->get())
149 this->counter().ref();
150 }
151
158 : DLReferenceCountPtr(other.get()) {}
159
168 template <class U>
169 requires std::convertible_to<U*, T*>
171 : DLReferenceCountPtr(other.get()) {}
172
181 this->raw = std::exchange(other.raw, nullptr);
182 }
183
194 template <class U>
195 requires std::convertible_to<U*, T*>
197 this->raw = std::exchange(other.raw, nullptr);
198 }
199
201 if (this->get())
202 this->counter().unref();
203 }
204
212 template <class U>
213 requires std::convertible_to<U*, T*>
215 if (this->get())
216 this->counter().unref();
217 this->raw = other->get();
218 if (this->get())
219 this->counter().ref();
220 return *this;
221 }
222
232 template <class U>
233 requires std::convertible_to<U*, T*>
235 if (this->get())
236 this->counter().unref();
237 this->raw = std::exchange(other.raw, nullptr);
238 return *this;
239 }
240
245 void reset() {
246 if (this->raw)
247 this->counter().unref();
248 this->raw = nullptr;
249 }
250
258 template <class U>
259 requires std::convertible_to<U*, T*>
260 void reset(U* raw) {
261 if (this->raw)
262 this->counter().unref();
263 this->raw = raw;
264 if (raw)
265 this->counter().ref();
266 }
267
274 std::swap(this->raw, other.raw);
275 }
276
282 T* get() const noexcept {
283 return this->raw;
284 }
285
293 T& operator*() const noexcept {
294 return *this->get();
295 }
296
302 T* operator->() const noexcept {
303 return this->get();
304 }
305
311 explicit operator bool() const noexcept {
312 return this->get();
313 }
314
315private:
316 DLReferenceCountObject& counter() noexcept {
317 return static_cast<DLReferenceCountObject&>(*this->raw);
318 }
319
320 T* raw;
321};
322
327template <typename T, typename U>
328inline bool operator==(const DLReferenceCountPtr<T>& lhs,
329 const DLReferenceCountPtr<U>& rhs) {
330 return lhs.get() == rhs.get();
331}
332
337template <typename T, typename U>
338inline std::strong_ordering operator<=>(const DLReferenceCountPtr<T>& lhs,
339 const DLReferenceCountPtr<U>& rhs) {
340 return lhs.get() <=> rhs.get();
341}
342
347template <typename T, typename U>
348inline bool operator==(const DLReferenceCountPtr<U>& lhs, std::nullptr_t) {
349 return lhs.get() == nullptr;
350}
351
356template <typename T, typename U>
357inline std::strong_ordering operator<=>(const DLReferenceCountPtr<T>& lhs,
358 std::nullptr_t) {
359 return lhs.get() <=> nullptr;
360}
361
362LIBER_ASSERTS_BEGIN(DLReferenceCountObject);
363LIBER_ASSERT_SIZE(0x10);
364LIBER_ASSERTS_END;
365
367LIBER_ASSERTS_TEMPLATE_BEGIN(DLReferenceCountPtr, dummy_rfco);
368LIBER_ASSERT_SIZE(0x8);
369LIBER_ASSERTS_END;
370} // namespace DLUT
371
380template <typename T, typename... Args>
381 requires std::derived_from<T, DLUT::DLReferenceCountObject>
382[[nodiscard]] inline auto make_refcounted(Args&&... args) {
384 using altraits = std::allocator_traits<decltype(allocator)>;
385 T* p = altraits::allocate(allocator, 1);
386 if (!p)
387 return DLUT::DLReferenceCountPtr<T>(nullptr);
388 altraits::construct(allocator, p, std::forward<Args>(args)...);
390}
391} // namespace from
Base class used for non-copyable, but movable objects.
Definition utility.hpp:27
Class for implementing reference counting garbage collection.
Definition utility.hpp:47
DLReferenceCountObject() noexcept=default
Protected DLReferenceCountObject constructor.
void ref() noexcept
Increment the object's reference count.
Definition utility.hpp:75
void unref()
Unreference object; there cannot be more ref() calls than unref() calls.
Definition utility.hpp:86
virtual void deleter()
The deleter method to call when reference count reaches zero.
Definition utility.hpp:55
int count() const noexcept
Get number of references to object.
Definition utility.hpp:67
A refcounted pointer that models std::shared_ptr<T>.
Definition utility.hpp:126
void reset(U *raw)
Replace the owned pointer (and decrement reference count).
Definition utility.hpp:260
void reset()
Reset the owned pointer (and decrement reference count).
Definition utility.hpp:245
T * operator->() const noexcept
Member access for the managed object.
Definition utility.hpp:302
T & operator*() const noexcept
Dereference the managed pointer.
Definition utility.hpp:293
DLReferenceCountPtr(DLReferenceCountPtr &&other) noexcept
Construct a new DLReferenceCountPtr object (move).
Definition utility.hpp:180
DLReferenceCountPtr & operator=(DLReferenceCountPtr< U > &&other)
Move assignment operator.
Definition utility.hpp:234
DLReferenceCountPtr(std::nullptr_t) noexcept
Construct a new DLReferenceCountPtr (std::nullptr_t).
Definition utility.hpp:136
DLReferenceCountPtr(const DLReferenceCountPtr &other) noexcept
Construct a new DLReferenceCountPtr object (copy).
Definition utility.hpp:157
DLReferenceCountPtr & operator=(const DLReferenceCountPtr< U > &other)
Copy assignment operator.
Definition utility.hpp:214
void swap(DLReferenceCountPtr &other)
Swap for DLReferenceCountPtr.
Definition utility.hpp:273
DLReferenceCountPtr(const DLReferenceCountPtr< U > &other) noexcept
Construct a new DLReferenceCountPtr object (copy, pointer conversion).
Definition utility.hpp:170
T * get() const noexcept
Get the managed pointer.
Definition utility.hpp:282
DLReferenceCountPtr(DLReferenceCountPtr< U > &&other) noexcept
Construct a new DLReferenceCountPtr object (move, pointer conversion).
Definition utility.hpp:196
DLReferenceCountPtr(U *raw) noexcept
Construct a new DLReferenceCountPtr (raw pointer).
Definition utility.hpp:147
The main libER stand-in for ER allocator proxies.
Definition from_allocator.hpp:308
ELDEN RING allocation interface and from::allocator.
from::allocator< T > get_allocator_of(const T *p) noexcept
Get the allocator of an object allocated by ELDEN RING.
Definition from_allocator.hpp:426
Definition utility.hpp:366
std::strong_ordering operator<=>(const DLReferenceCountPtr< T > &lhs, const DLReferenceCountPtr< U > &rhs)
DLReferenceCountPtr comparison.
Definition utility.hpp:338
auto make_refcounted(Args &&... args)
Construct a reference counted object with the default libER allocator.
Definition utility.hpp:382
bool operator==(const DLReferenceCountPtr< T > &lhs, const DLReferenceCountPtr< U > &rhs)
DLReferenceCountPtr comparison.
Definition utility.hpp:328