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
45public:
46 LIBER_CLASS(DLReferenceCountObject);
47
48 DLReferenceCountObject() : counter(0){};
49
54 virtual void deleter() = 0;
55 virtual ~DLReferenceCountObject() = default;
56
57private:
58 template <typename T>
59 requires std::derived_from<T, DLReferenceCountObject>
60 friend class DLReferenceCountPtr;
61
62 // Number of references to object
63 int count() const noexcept {
64 return this->counter.load(std::memory_order_relaxed);
65 }
66
67 // Reference object
68 void ref() noexcept {
69 ++this->counter;
70 }
71
72 // Unreference object; there cannot
73 // be more ref() calls than unref() calls
74 void unref() {
75 int value = this->counter.fetch_add(-1, std::memory_order_seq_cst);
76 if (value == 1)
77 this->deleter();
78 else if (value < 1)
79 throw std::runtime_error("bad unref() call");
80 }
81
82 std::atomic_int counter;
83};
84
85// A refcounted pointer that models std::shared_ptr
86// Use from::make_refcounted<T>(...) to create refcounted objects
87// These objects must derive from DLReferenceCountObject
97template <typename T>
98 requires std::derived_from<T, DLReferenceCountObject>
100public:
101 LIBER_CLASS(DLReferenceCountPtr);
102
103 DLReferenceCountPtr() noexcept : raw(nullptr) {}
104
109 DLReferenceCountPtr(std::nullptr_t) noexcept : raw(nullptr) {}
110
118 template <class U>
119 requires std::convertible_to<U*, T*>
120 explicit DLReferenceCountPtr(U* raw) noexcept : raw(raw) {
121 if (this->get())
122 this->counter().ref();
123 }
124
131 : DLReferenceCountPtr(other.get()) {}
132
141 template <class U>
142 requires std::convertible_to<U*, T*>
144 : DLReferenceCountPtr(other.get()) {}
145
154 this->raw = std::exchange(other.raw, nullptr);
155 }
156
167 template <class U>
168 requires std::convertible_to<U*, T*>
170 this->raw = std::exchange(other.raw, nullptr);
171 }
172
174 if (this->get())
175 this->counter().unref();
176 }
177
185 template <class U>
186 requires std::convertible_to<U*, T*>
188 if (this->get())
189 this->counter().unref();
190 this->raw = other->get();
191 if (this->get())
192 this->counter().ref();
193 return *this;
194 }
195
205 template <class U>
206 requires std::convertible_to<U*, T*>
208 if (this->get())
209 this->counter().unref();
210 this->raw = std::exchange(other.raw, nullptr);
211 return *this;
212 }
213
218 void reset() {
219 if (this->raw)
220 this->counter().unref();
221 this->raw = nullptr;
222 }
223
231 template <class U>
232 requires std::convertible_to<U*, T*>
233 void reset(U* raw) {
234 if (this->raw)
235 this->counter().unref();
236 this->raw = raw;
237 if (raw)
238 this->counter().ref();
239 }
240
247 std::swap(this->raw, other.raw);
248 }
249
255 T* get() const noexcept {
256 return this->raw;
257 }
258
266 T& operator*() const noexcept {
267 return *this->get();
268 }
269
275 T* operator->() const noexcept {
276 return this->get();
277 }
278
284 explicit operator bool() const noexcept {
285 return this->get();
286 }
287
288private:
289 DLReferenceCountObject& counter() noexcept {
290 return static_cast<DLReferenceCountObject&>(*this->raw);
291 }
292
293 T* raw;
294};
295
300template <typename T, typename U>
301inline bool operator==(const DLReferenceCountPtr<T>& lhs,
302 const DLReferenceCountPtr<U>& rhs) {
303 return lhs.get() == rhs.get();
304}
305
310template <typename T, typename U>
311inline std::strong_ordering operator<=>(const DLReferenceCountPtr<T>& lhs,
312 const DLReferenceCountPtr<U>& rhs) {
313 return lhs.get() <=> rhs.get();
314}
315
320template <typename T, typename U>
321inline bool operator==(const DLReferenceCountPtr<U>& lhs, std::nullptr_t) {
322 return lhs.get() == nullptr;
323}
324
329template <typename T, typename U>
330inline std::strong_ordering operator<=>(const DLReferenceCountPtr<T>& lhs,
331 std::nullptr_t) {
332 return lhs.get() <=> nullptr;
333}
334
335LIBER_ASSERTS_BEGIN(DLReferenceCountObject);
336LIBER_ASSERT_SIZE(0x10);
337LIBER_ASSERTS_END;
338
340LIBER_ASSERTS_TEMPLATE_BEGIN(DLReferenceCountPtr, dummy_rfco);
341LIBER_ASSERT_SIZE(0x8);
342LIBER_ASSERTS_END;
343} // namespace DLUT
344
352template <typename T, typename... Args>
353 requires std::derived_from<T, DLUT::DLReferenceCountObject>
355 Args&&... args) {
356 return allocate_refcounted(from::allocator<T>{},
357 std::forward<Args>(args)...);
358}
359} // namespace from
Base class used for non-copyable, but movable objects.
Definition utility.hpp:27
Abstract class for implementing reference counting garbage collection.
Definition utility.hpp:44
virtual void deleter()=0
The deleter method to call when reference count reaches zero.
A refcounted pointer that models std::shared_ptr<T>.
Definition utility.hpp:99
void reset(U *raw)
Replace the owned pointer (and decrement reference count).
Definition utility.hpp:233
void reset()
Reset the owned pointer (and decrement reference count).
Definition utility.hpp:218
T * operator->() const noexcept
Member access for the managed object.
Definition utility.hpp:275
T & operator*() const noexcept
Dereference the managed pointer.
Definition utility.hpp:266
DLReferenceCountPtr(DLReferenceCountPtr &&other) noexcept
Construct a new DLReferenceCountPtr object (move).
Definition utility.hpp:153
DLReferenceCountPtr & operator=(DLReferenceCountPtr< U > &&other)
Move assignment operator.
Definition utility.hpp:207
DLReferenceCountPtr(std::nullptr_t) noexcept
Construct a new DLReferenceCountPtr (std::nullopt).
Definition utility.hpp:109
DLReferenceCountPtr(const DLReferenceCountPtr &other) noexcept
Construct a new DLReferenceCountPtr object (copy).
Definition utility.hpp:130
DLReferenceCountPtr & operator=(const DLReferenceCountPtr< U > &other)
Copy assignment operator.
Definition utility.hpp:187
void swap(DLReferenceCountPtr &other)
Swap for DLReferenceCountPtr.
Definition utility.hpp:246
DLReferenceCountPtr(const DLReferenceCountPtr< U > &other) noexcept
Construct a new DLReferenceCountPtr object (copy, pointer conversion).
Definition utility.hpp:143
T * get() const noexcept
Get the managed pointer.
Definition utility.hpp:255
DLReferenceCountPtr(DLReferenceCountPtr< U > &&other) noexcept
Construct a new DLReferenceCountPtr object (move, pointer conversion).
Definition utility.hpp:169
DLReferenceCountPtr(U *raw) noexcept
Construct a new DLReferenceCountPtr (raw pointer).
Definition utility.hpp:120
The main libER stand-in for ER allocator proxies.
Definition from_allocator.hpp:310
ELDEN RING allocation interface and from::allocator.
Definition utility.hpp:339
std::strong_ordering operator<=>(const DLReferenceCountPtr< T > &lhs, const DLReferenceCountPtr< U > &rhs)
DLReferenceCountPtr comparison.
Definition utility.hpp:311
bool operator==(const DLReferenceCountPtr< T > &lhs, const DLReferenceCountPtr< U > &rhs)
DLReferenceCountPtr comparison.
Definition utility.hpp:301
DLUT::DLReferenceCountPtr< T > make_refcounted(Args &&... args)
Construct a reference counted object with the default libER allocator.
Definition utility.hpp:354