blob: 72a9b860bc7553f3e491b7bc76c1f7ad1f931cdc (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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);
}
}
}
};
|