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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
#include <cstdint>
#include <stdexcept>
#ifndef SHARED_PTR_HPP
#define SHARED_PTR_HPP
namespace usu
{
template <typename T>
class shared_ptr
{
public:
shared_ptr() :
m_references(new std::uint32_t(0)), m_rawPtr(nullptr)
{
}
shared_ptr(T* rawPtr) :
m_references(new std::uint32_t(1)), m_rawPtr(rawPtr)
{
}
shared_ptr(const shared_ptr<T>& ptr) :
m_references(ptr.m_references), m_rawPtr(ptr.m_rawPtr)
{
(*m_references)++;
}
shared_ptr(shared_ptr<T>&& ptr) :
m_references(ptr.m_references), m_rawPtr(ptr.m_rawPtr)
{
ptr.m_references = nullptr;
ptr.m_rawPtr = nullptr;
}
~shared_ptr()
{
maybeDeallocate();
};
shared_ptr<T>& operator=(const shared_ptr<T>& rhs)
{
maybeDeallocate();
m_references = rhs.m_references;
(*m_references)++;
m_rawPtr = rhs.m_rawPtr;
return *this;
}
shared_ptr<T>& operator=(shared_ptr<T>&& rhs)
{
std::swap(m_references, rhs.m_references);
std::swap(m_rawPtr, rhs.m_rawPtr);
return *this;
}
T operator*() { return *m_rawPtr; }
T* operator->() { return m_rawPtr; }
T* get() { return m_rawPtr; }
std::uint32_t use_count() { return *m_references; }
private:
std::uint32_t* m_references;
T* m_rawPtr;
void maybeDeallocate()
{
if (m_references != nullptr)
{
(*m_references)--;
if (*m_references == 0)
{
delete m_references;
if (m_rawPtr != nullptr)
delete m_rawPtr;
}
}
}
};
template <typename T>
class shared_ptr<T[]>
{
public:
shared_ptr() :
m_references(new std::uint32_t(0)), m_rawPtr(nullptr), m_len(0)
{
}
shared_ptr(T* rawPtr, std::size_t len) :
m_references(new std::uint32_t(1)), m_rawPtr(rawPtr), m_len(len)
{
}
~shared_ptr()
{
if (m_references != nullptr)
{
(*m_references)--;
if (*m_references == 0)
{
delete m_references;
if (m_rawPtr != nullptr)
delete[] m_rawPtr;
}
}
};
std::size_t size() { return m_len; }
T& operator[](std::uint32_t index)
{
if (index >= m_len)
throw std::invalid_argument("Index is out of range");
return m_rawPtr[index];
}
private:
std::uint32_t* m_references;
T* m_rawPtr;
std::size_t m_len;
};
template <typename T, typename... Args>
shared_ptr<T> make_shared(Args&&... args)
{
return shared_ptr<T>(new T(std::forward<Args>(args)...));
}
template <typename T, unsigned int N>
shared_ptr<T[]> make_shared_array()
{
return shared_ptr<T[]>(new T[N], N);
}
} // namespace usu
#endif // SHARED_PTR_HPP
|