aboutsummaryrefslogtreecommitdiff
path: root/source/10-common/RcPtr.hpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2023-09-20 23:58:58 -0700
committerrtk0c <[email protected]>2023-09-20 23:58:58 -0700
commitf138311d2d2e0cc9ba0496d523bb46f2c1c9fb73 (patch)
treef96100a813a4ffb28dcd074455d3a2f8ee426430 /source/10-common/RcPtr.hpp
Copy from the PlasticSCM repo, replace vendored glm wtih conan
Diffstat (limited to 'source/10-common/RcPtr.hpp')
-rw-r--r--source/10-common/RcPtr.hpp120
1 files changed, 120 insertions, 0 deletions
diff --git a/source/10-common/RcPtr.hpp b/source/10-common/RcPtr.hpp
new file mode 100644
index 0000000..e3e420e
--- /dev/null
+++ b/source/10-common/RcPtr.hpp
@@ -0,0 +1,120 @@
+#pragma once
+
+#include "Macros.hpp"
+#include "TypeTraits.hpp"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <type_traits>
+
+class RefCounted {
+public:
+ // DO NOT MODIFY this field, unless explicitly documented the use
+ uint32_t refCount = 0;
+ uint32_t weakCount = 0; // TODO implement
+};
+
+template <typename T, typename TDeleter = DefaultDeleter<T>>
+class RcPtr : TDeleter {
+private:
+ static_assert(std::is_base_of_v<RefCounted, T>);
+ T* mPtr;
+
+public:
+ RcPtr()
+ : mPtr{ nullptr } {
+ }
+
+ explicit RcPtr(T* ptr)
+ : mPtr{ ptr } {
+ if (ptr) {
+ ++ptr->RefCounted::refCount;
+ }
+ }
+
+ ~RcPtr() {
+ CleanUp();
+ }
+
+ void Attach(T* ptr) {
+ CleanUp();
+ mPtr = ptr;
+ if (ptr) {
+ ++ptr->RefCounted::refCount;
+ }
+ }
+
+ void Detatch() {
+ CleanUp();
+ mPtr = nullptr;
+ }
+
+ RcPtr(const RcPtr& that)
+ : mPtr{ that.mPtr } {
+ if (mPtr) {
+ ++mPtr->RefCounted::refCount;
+ }
+ }
+
+ RcPtr& operator=(const RcPtr& that) {
+ CleanUp();
+ mPtr = that.mPtr;
+ if (mPtr) {
+ ++mPtr->RefCounted::refCount;
+ }
+ return *this;
+ }
+
+ RcPtr(RcPtr&& that)
+ : mPtr{ that.mPtr } {
+ that.mPtr = nullptr;
+ }
+
+ RcPtr& operator=(RcPtr&& that) {
+ CleanUp();
+ mPtr = that.mPtr;
+ that.mPtr = nullptr;
+ return *this;
+ }
+
+ template <typename TBase>
+ requires std::is_base_of_v<TBase, T>
+ operator RcPtr<TBase>() const {
+ return RcPtr<TBase>(mPtr);
+ }
+
+ bool operator==(std::nullptr_t ptr) const {
+ return mPtr == nullptr;
+ }
+
+ bool operator==(const T* ptr) const {
+ return mPtr == ptr;
+ }
+
+ bool operator==(T* ptr) const {
+ return mPtr == ptr;
+ }
+
+ template <typename TThat>
+ bool operator==(const RcPtr<TThat>& ptr) const {
+ return mPtr == ptr.Get();
+ }
+
+ T* Get() const {
+ return mPtr;
+ }
+
+ T& operator*() const { return *mPtr; }
+ T* operator->() const { return mPtr; }
+
+private:
+ void CleanUp() {
+ if (mPtr) {
+ --mPtr->RefCounted::refCount;
+ if (mPtr->RefCounted::refCount == 0) {
+ TDeleter::operator()(mPtr);
+ }
+ }
+ }
+};