Chira Engine
A customizable MIT-licensed game engine.
SharedPointer.h
1 #pragma once
2 
3 #include <core/Assertions.h>
4 
5 namespace chira {
6 
7 enum class CastType {
8  STATIC_CAST,
9  DYNAMIC_CAST,
10  REINTERPRET_CAST,
11  ASSERT_CAST,
12  C_CAST
13 };
14 
16  unsigned int refCount = 1;
21  unsigned int holderAmountForDelete = 1;
22  SharedPointerMetadata() = default;
23  explicit SharedPointerMetadata(unsigned int refCount_) : refCount(refCount_) {}
24  SharedPointerMetadata(unsigned int refCount_, unsigned int holderAmountForDelete_) : refCount(refCount_), holderAmountForDelete(holderAmountForDelete_) {}
25  SharedPointerMetadata(const SharedPointerMetadata& other) = delete;
26  SharedPointerMetadata& operator=(const SharedPointerMetadata& other) = delete;
27  SharedPointerMetadata(SharedPointerMetadata&& other) = delete;
28  SharedPointerMetadata& operator=(SharedPointerMetadata&& other) = delete;
29 };
30 
31 template<typename T> class SharedPointer {
32 public:
33  SharedPointer() = default;
34  explicit SharedPointer(T* inputPtr) : ptr(inputPtr), data(new SharedPointerMetadata{1}) {}
35  SharedPointer(T* inputPtr, SharedPointerMetadata* data_) : ptr(inputPtr), data(data_) {
36  if (this->data) {
37  this->data->refCount++;
38  }
39  }
40  SharedPointer<T>& operator=(const SharedPointer<T>& other) noexcept {
41  if (this == &other)
42  return *this;
43 
44  if ((this->data) && (this->data->refCount <= this->data->holderAmountForDelete)) {
45  delete this->ptr;
46  delete this->data;
47  }
48  this->ptr = other.ptr;
49  this->data = other.data;
50  if (this->data) {
51  this->data->refCount++;
52  }
53  return *this;
54  }
55  SharedPointer(const SharedPointer<T>& other) noexcept {
56  if (this == &other)
57  return;
58 
59  if ((this->data) && (this->data->refCount <= this->data->holderAmountForDelete)) {
60  delete this->ptr;
61  delete this->data;
62  }
63  this->ptr = other.ptr;
64  this->data = other.data;
65  if (this->data) {
66  this->data->refCount++;
67  }
68  }
69  SharedPointer<T>& operator=(SharedPointer<T>&& other) noexcept {
70  if ((this->data) && (this->data->refCount <= this->data->holderAmountForDelete)) {
71  delete this->ptr;
72  delete this->data;
73  }
74  this->ptr = other.ptr;
75  this->data = other.data;
76  other.ptr = nullptr;
77  other.data = nullptr;
78  return *this;
79  }
80  SharedPointer(SharedPointer<T>&& other) noexcept {
81  *this = std::move(other);
82  }
83  ~SharedPointer() {
84  if (!this->data) {
85  delete this->ptr;
86  return;
87  }
88  this->data->refCount--;
89  if (this->data->refCount == this->data->holderAmountForDelete) {
90  delete this->ptr;
91  }
92  if (this->data->refCount == 0) {
93  delete this->data;
94  }
95  }
96  T* get() const noexcept {
97  return this->ptr;
98  }
99  T& operator*() const {
100  return *this->ptr;
101  }
102  T* operator->() const noexcept {
103  return this->ptr;
104  }
105  explicit operator bool() const {
106  return bool(this->ptr);
107  }
108  bool operator!() const {
109  return !(bool(this->ptr));
110  }
111  [[nodiscard]] unsigned int useCount() const {
112  if (this->data)
113  return this->data->refCount;
114  else
115  return 0;
116  }
117  [[nodiscard]] unsigned int getHolderAmountForDelete() const {
118  if (this->data) {
119  return this->data->holderAmountForDelete;
120  } else {
121  return 0;
122  }
123  }
124  void setHolderAmountForDelete(unsigned int newHolderAmountForDelete) const {
125  if (this->data) {
126  this->data->holderAmountForDelete = newHolderAmountForDelete;
127  }
128  }
129  template<typename U>
130  SharedPointer<U> castStatic() const {
131  return SharedPointer<U>(static_cast<U*>(this->ptr), this->data);
132  }
133  template<typename U>
134  SharedPointer<U> castDynamic() const {
135  return SharedPointer<U>(dynamic_cast<U*>(this->ptr), this->data);
136  }
137  template<typename U>
138  SharedPointer<U> castAssert() const {
139  return SharedPointer<U>(assert_cast<U*>(this->ptr), this->data);
140  }
141  template<typename U>
142  SharedPointer<U> castReinterpret() const {
143  return SharedPointer<U>(reinterpret_cast<U*>(this->ptr), this->data);
144  }
145  template<typename U>
146  SharedPointer<U> cast(CastType type = CastType::ASSERT_CAST) const {
147  switch (type) {
148  using enum CastType;
149  case STATIC_CAST:
150  return this->castStatic<U>();
151  case DYNAMIC_CAST:
152  return this->castDynamic<U>();
153  case REINTERPRET_CAST:
154  return this->castReinterpret<U>();
155  case ASSERT_CAST:
156  return this->castAssert<U>();
157  case C_CAST:
158  return SharedPointer<U>((U*)(this->ptr), this->data);
159  CHIRA_NO_DEFAULT;
160  }
161  }
162 protected:
163  T* ptr = nullptr;
164  SharedPointerMetadata* data = nullptr;
165 };
166 
167 } // namespace chira
unsigned int holderAmountForDelete
If the refcount is less than or equal to this number in the destructor (after it is subtracted once),...
Definition: SharedPointer.h:21