-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathRefCount.hpp
114 lines (92 loc) · 2.39 KB
/
RefCount.hpp
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
#pragma once
#include <nstd/Atomic.hpp>
class RefCount
{
public:
class Object;
template <class C = Object> class Ptr
{
public:
Ptr() : refObj(0), obj(0) {}
Ptr(const Ptr& other) : refObj(other.refObj), obj(other.obj)
{
if(refObj)
Atomic::increment(refObj->ref);
}
template <class D> Ptr(D* obj) : refObj(obj), obj(obj)
{
if(refObj)
Atomic::increment(refObj->ref);
}
template <class D> Ptr(const Ptr<D>& other) : refObj(other.refObj), obj(other.obj)
{
if(refObj)
Atomic::increment(refObj->ref);
}
~Ptr()
{
if(refObj && Atomic::decrement(refObj->ref) == 0)
delete refObj;
}
Ptr& operator=(const Ptr& other)
{
if(other.refObj)
Atomic::increment(other.refObj->ref);
if(refObj && Atomic::decrement(refObj->ref) == 0)
delete refObj;
refObj = other.refObj;
obj = other.obj;
return *this;
}
Ptr& operator=(C* obj)
{
Object* refObj = obj;
if(refObj)
Atomic::increment(refObj->ref);
if(this->refObj && Atomic::decrement(this->refObj->ref) == 0)
delete this->refObj;
this->refObj = refObj;
this->obj = obj;
return *this;
}
template <class D> Ptr& operator=(const Ptr<D>& other)
{
if(other.refObj)
Atomic::increment(other.refObj->ref);
if(refObj && Atomic::decrement(refObj->ref) == 0)
delete refObj;
refObj = other.refObj;
obj = other.obj;
return *this;
}
C& operator*() const {return *obj;}
C* operator->() const {return obj;}
template <class D> bool operator==(D* other) const {return obj == other;}
template <class D> bool operator!=(D* other) const {return obj != other;}
template <class D> bool operator==(const Ptr<D>& other) const {return obj == other.obj;}
template <class D> bool operator!=(const Ptr<D>& other) const {return obj != other.obj;}
operator bool() const {return obj != 0;}
void swap(Ptr& other)
{
C* tmp = other.obj;
other.obj = obj;
obj = tmp;
}
private:
Object* refObj;
C* obj;
template<class D> friend class Ptr;
};
class Object
{
public:
Object() : ref(0) {}
protected:
virtual ~Object() {}
private:
usize ref;
Object(const Object&);
Object& operator=(const Object&);
template<class C> friend class Ptr;
};
};