Add member<T> for non-pointer member varibables and stack locals.
[zcpointer.git] / zcpointer.h
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef ZCPOINTER_ZCPOINTER_H_
16 #define ZCPOINTER_ZCPOINTER_H_
17
18 #include <limits>
19 #include <memory>
20 #include <forward_list>
21 #include <stdexcept>
22 #include <utility>
23
24 namespace zc {
25
26 class UseAfterFreeError : public std::logic_error {
27 public:
28 using std::logic_error::logic_error;
29 };
30
31 #if defined(ZCPOINTER_TRACK_REFS) && ZCPOINTER_TRACK_REFS
32
33 template <typename T> class ref;
34
35 namespace internal {
36
37 template <typename T>
38 class OwnedPtrDeleter {
39 public:
40 OwnedPtrDeleter() {}
41 ~OwnedPtrDeleter() {}
42
43 OwnedPtrDeleter(OwnedPtrDeleter&& other) : refs_(std::move(other.refs_)) {
44 }
45
46 void operator=(const OwnedPtrDeleter& o) {
47 refs_ = o.refs_;
48 }
49
50 void operator()(T* t) const {
51 for (auto& ref : refs_) {
52 ref->MarkDeleted();
53 }
54 delete t;
55 }
56
57 protected:
58 friend class ref<T>;
59
60 void AddRef(ref<T>* ref) {
61 refs_.push_front(ref);
62 }
63
64 void RemoveRef(ref<T>* ref) {
65 refs_.remove(ref);
66 }
67
68 private:
69 std::forward_list<ref<T>*> refs_;
70 };
71
72 void RaiseUseAfterFree(const char* error) __attribute__((noreturn));
73
74 } // namespace internal
75
76 template <typename T>
77 class owned : public std::unique_ptr<T, internal::OwnedPtrDeleter<T>> {
78 private:
79 using Deleter = internal::OwnedPtrDeleter<T>;
80
81 public:
82 using std::unique_ptr<T, Deleter>::unique_ptr;
83
84 ref<T> get() {
85 return ref<T>(*this);
86 }
87
88 private:
89 T* get() const {
90 return this->std::unique_ptr<T, Deleter>::get();
91 }
92 };
93
94 template <typename T>
95 class ref {
96 public:
97 ref() : ptr_(nullptr) {}
98
99 ref(std::nullptr_t) : ref() {}
100
101 explicit ref(owned<T>& o) : ptr_(nullptr) {
102 if (o != nullptr) {
103 ptr_ = &o;
104 ptr_->get_deleter().AddRef(this);
105 }
106 }
107
108 ref(const ref<T>& r) {
109 *this = r;
110 }
111
112 ref<T>& operator=(const ref<T>& o) {
113 ptr_ = o.ptr_;
114 if (ptr_ != nullptr && !IsDeleted()) {
115 ptr_->get_deleter().AddRef(this);
116 }
117 return *this;
118 }
119
120 ~ref() {
121 if (ptr_ != nullptr && !IsDeleted()) {
122 ptr_->get_deleter().RemoveRef(this);
123 }
124 MarkDeleted();
125 }
126
127 T* operator->() const {
128 CheckDeleted();
129 return ptr_->operator->();
130 }
131
132 bool operator==(const ref<T>& r) const {
133 if (ptr_ == nullptr) {
134 return r.ptr_ == nullptr;
135 } else {
136 return ptr_ == r.ptr_ && *ptr_ == *r.ptr_;
137 }
138 }
139
140 bool operator==(std::nullptr_t) const {
141 return ptr_ == nullptr;
142 }
143
144 bool operator!=(const ref<T>& r) const {
145 return !(*this == r);
146 }
147
148 protected:
149 friend class internal::OwnedPtrDeleter<T>;
150
151 void MarkDeleted() {
152 ptr_ = DeletedSentinel();
153 }
154
155 private:
156 void CheckDeleted() const {
157 if (IsDeleted()) {
158 internal::RaiseUseAfterFree("attempt to access deleted pointer");
159 }
160 }
161
162 bool IsDeleted() const {
163 return ptr_ == DeletedSentinel();
164 }
165
166 inline static owned<T>* DeletedSentinel() {
167 return reinterpret_cast<owned<T>*>(std::numeric_limits<uintptr_t>::max());
168 }
169
170 owned<T>* ptr_;
171 };
172
173 template <typename T>
174 class member {
175 public:
176 template <typename... Args>
177 explicit member(Args&&... args)
178 : t_(new T(std::forward<Args>(args)...)) {
179 }
180
181 ref<T> operator&() {
182 return t_.get();
183 }
184
185 T* operator->() {
186 return t_.operator->();
187 }
188
189 const T* operator->() const {
190 return t_.operator->();
191 }
192
193 private:
194 owned<T> t_;
195 };
196
197 #else
198
199 template <typename T>
200 using owned = std::unique_ptr<T>;
201
202 template <typename T>
203 using ref = T*;
204
205 template <typename T>
206 class member : public T {
207 public:
208 using T::T;
209
210 T* operator->() {
211 return this;
212 }
213
214 const T* operator->() const {
215 return this;
216 }
217 };
218
219 #endif
220
221 } // namespace zc
222
223 #endif // ZCPOINTER_ZCPOINTER_H_