Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: third_party/base/nonstd_unique_ptr.h

Issue 1351383004: Change nonstd::unique_ptr to take a custom deleter. (Closed) Base URL: https://pdfium.googlesource.com/pdfium@master
Patch Set: address comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 Google Inc. All Rights Reserved. 1 // Copyright 2013 Google Inc. All Rights Reserved.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are 4 // modification, are permitted provided that the following conditions are
5 // met: 5 // met:
6 // 6 //
7 // * Redistributions of source code must retain the above copyright 7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer. 8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above 9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer 10 // copyright notice, this list of conditions and the following disclaimer
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 #ifndef NONSTD_UNIQUE_PTR_H_ 66 #ifndef NONSTD_UNIQUE_PTR_H_
67 #define NONSTD_UNIQUE_PTR_H_ 67 #define NONSTD_UNIQUE_PTR_H_
68 68
69 // This is an implementation designed to match the anticipated future C++11 69 // This is an implementation designed to match the anticipated future C++11
70 // implementation of the unique_ptr class. 70 // implementation of the unique_ptr class.
71 71
72 #include <assert.h> 72 #include <assert.h>
73 #include <stddef.h> 73 #include <stddef.h>
74 #include <stdlib.h> 74 #include <stdlib.h>
75 75
76 #include <algorithm>
Jeffrey Yasskin 2015/09/19 00:00:47 I don't see any uses of these two headers. You ar
Lei Zhang 2015/09/23 00:38:56 Done.
77 #include <sstream>
78
79 #include "template_util.h"
80
76 namespace nonstd { 81 namespace nonstd {
77 82
78 // Replacement for move, but doesn't allow things that are already 83 // Replacement for move, but doesn't allow things that are already
79 // rvalue references. 84 // rvalue references.
80 template <class T> 85 template <class T>
81 T&& move(T& t) { 86 T&& move(T& t) {
82 return static_cast<T&&>(t); 87 return static_cast<T&&>(t);
83 } 88 }
84 89
90 // Function object which deletes its parameter, which must be a pointer.
91 // If C is an array type, invokes 'delete[]' on the parameter; otherwise,
92 // invokes 'delete'. The default deleter for scoped_ptr<T>.
Jeffrey Yasskin 2015/09/19 00:00:47 s/scoped_ptr/unique_ptr/
Lei Zhang 2015/09/23 00:38:55 Done.
93 template <class T>
94 struct DefaultDeleter {
95 DefaultDeleter() {}
96 template <typename U>
97 DefaultDeleter(const DefaultDeleter<U>& other) {
98 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
99 // if U* is implicitly convertible to T* and U is not an array type.
100 //
101 // Correct implementation should use SFINAE to disable this
102 // constructor. However, since there are no other 1-argument constructors,
103 // using a static_assert() based on is_convertible<> and requiring
104 // complete types is simpler and will cause compile failures for equivalent
105 // misuses.
106 //
107 // Note, the is_convertible<U*, T*> check also ensures that U is not an
108 // array. T is guaranteed to be a non-array, so any U* where U is an array
109 // cannot convert to T*.
110 enum { T_must_be_complete = sizeof(T) };
111 enum { U_must_be_complete = sizeof(U) };
112 static_assert((pdfium::base::is_convertible<U*, T*>::value),
113 "U_ptr_must_implicitly_convert_to_T_ptr");
114 }
115 inline void operator()(T* ptr) const {
116 enum { type_must_be_complete = sizeof(T) };
117 delete ptr;
118 }
119 };
120
121 // Specialization of DefaultDeleter for array types.
122 template <class T>
123 struct DefaultDeleter<T[]> {
124 inline void operator()(T* ptr) const {
125 enum { type_must_be_complete = sizeof(T) };
126 delete[] ptr;
127 }
128
129 private:
130 // Disable this operator for any U != T because it is undefined to execute
131 // an array delete when the static type of the array mismatches the dynamic
132 // type.
133 //
134 // References:
135 // C++98 [expr.delete]p3
136 // http://cplusplus.github.com/LWG/lwg-defects.html#938
137 template <typename U>
138 void operator()(U* array) const;
139 };
140
141 template <class T, int n>
142 struct DefaultDeleter<T[n]> {
143 // Never allow someone to declare something like scoped_ptr<int[10]>.
144 static_assert(sizeof(T) == -1, "do_not_use_array_with_size_as_type");
145 };
146
147 namespace internal {
148
149 template <typename T>
150 struct ShouldAbortOnSelfReset {
Jeffrey Yasskin 2015/09/19 00:00:47 Can you drop this, and just use the C++11 behavior
Lei Zhang 2015/09/23 00:38:55 So, let the caller shoot themselves in the foot wi
Jeffrey Yasskin 2015/09/23 00:53:34 Yeah. ASan should save us in a lot of cases, and w
151 template <typename U>
152 static pdfium::base::internal::NoType Test(const typename U::AllowSelfReset*);
153
154 template <typename U>
155 static pdfium::base::internal::YesType Test(...);
156
157 static const bool value =
158 sizeof(Test<T>(0)) == sizeof(pdfium::base::internal::YesType);
159 };
160
85 // Common implementation for both pointers to elements and pointers to 161 // Common implementation for both pointers to elements and pointers to
86 // arrays. These are differentiated below based on the need to invoke 162 // arrays. These are differentiated below based on the need to invoke
87 // delete vs. delete[] as appropriate. 163 // delete vs. delete[] as appropriate.
88 template <class C> 164 template <class C, class D>
89 class unique_ptr_base { 165 class unique_ptr_base {
90 public: 166 public:
91
92 // The element type 167 // The element type
93 typedef C element_type; 168 typedef C element_type;
94 169
95 explicit unique_ptr_base(C* p) : ptr_(p) { } 170 explicit unique_ptr_base(C* p) : data_(p) {}
171
172 // Initializer for deleters that have data parameters.
173 unique_ptr_base(C* p, const D& d) : data_(p, d) {}
96 174
97 // Move constructor. 175 // Move constructor.
98 unique_ptr_base(unique_ptr_base<C>&& that) { 176 unique_ptr_base(unique_ptr_base<C, D>&& that)
99 ptr_ = that.ptr_; 177 : data_(that.release(), that.get_deleter()) {}
100 that.ptr_ = nullptr; 178
179 ~unique_ptr_base() {
180 enum { type_must_be_complete = sizeof(C) };
181 if (data_.ptr != nullptr) {
182 // Not using get_deleter() saves one function call in non-optimized
183 // builds.
184 static_cast<D&>(data_)(data_.ptr);
185 }
186 }
187
188 void reset(C* p = nullptr) {
189 // This is a self-reset, which is no longer allowed for default deleters:
190 // https://crbug.com/162971
191 assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
192
193 // Note that running data_.ptr = p can lead to undefined behavior if
194 // get_deleter()(get()) deletes this. In order to prevent this, reset()
195 // should update the stored pointer before deleting its old value.
196 //
197 // However, changing reset() to use that behavior may cause current code to
198 // break in unexpected ways. If the destruction of the owned object
199 // dereferences the scoped_ptr when it is destroyed by a call to reset(),
200 // then it will incorrectly dispatch calls to |p| rather than the original
201 // value of |data_.ptr|.
202 //
203 // During the transition period, set the stored pointer to nullptr while
204 // deleting the object. Eventually, this safety check will be removed to
205 // prevent the scenario initially described from occuring and
206 // http://crbug.com/176091 can be closed.
207 C* old = data_.ptr;
208 data_.ptr = nullptr;
209 if (old != nullptr)
210 static_cast<D&>(data_)(old);
211 data_.ptr = p;
101 } 212 }
102 213
103 // Accessors to get the owned object. 214 // Accessors to get the owned object.
104 // operator* and operator-> will assert() if there is no current object. 215 // operator* and operator-> will assert() if there is no current object.
105 C& operator*() const { 216 C& operator*() const {
Jeffrey Yasskin 2015/09/19 00:00:47 Could you disable unique_ptr<T[]>::operator* and o
Lei Zhang 2015/09/23 00:38:55 Moved out of the base impl.
106 assert(ptr_ != NULL); 217 assert(data_.ptr != nullptr);
107 return *ptr_; 218 return *data_.ptr;
108 } 219 }
109 C* operator->() const { 220 C* operator->() const {
110 assert(ptr_ != NULL); 221 assert(data_.ptr != nullptr);
111 return ptr_; 222 return data_.ptr;
112 } 223 }
113 C* get() const { return ptr_; } 224 C* get() const { return data_.ptr; }
225 D& get_deleter() { return data_; }
226 const D& get_deleter() const { return data_; }
114 227
115 // Comparison operators. 228 // Comparison operators.
116 // These return whether two unique_ptr refer to the same object, not just to 229 // These return whether two unique_ptr refer to the same object, not just to
117 // two different but equal objects. 230 // two different but equal objects.
118 bool operator==(C* p) const { return ptr_ == p; } 231 bool operator==(C* p) const { return data_.ptr == p; }
119 bool operator!=(C* p) const { return ptr_ != p; } 232 bool operator!=(C* p) const { return data_.ptr != p; }
120 233
121 // Swap two scoped pointers. 234 // Swap two scoped pointers.
122 void swap(unique_ptr_base& p2) { 235 void swap(unique_ptr_base& p2) {
123 C* tmp = ptr_; 236 Data tmp = data_;
124 ptr_ = p2.ptr_; 237 data_ = p2.data_;
125 p2.ptr_ = tmp; 238 p2.data_ = tmp;
126 } 239 }
127 240
128 // Release a pointer. 241 // Release a pointer.
129 // The return value is the current pointer held by this object. 242 // The return value is the current pointer held by this object.
130 // If this object holds a NULL pointer, the return value is NULL. 243 // If this object holds a NULL pointer, the return value is NULL.
131 // After this operation, this object will hold a NULL pointer, 244 // After this operation, this object will hold a NULL pointer,
132 // and will not own the object any more. 245 // and will not own the object any more.
133 C* release() { 246 C* release() {
134 C* retVal = ptr_; 247 C* ptr = data_.ptr;
135 ptr_ = NULL; 248 data_.ptr = nullptr;
136 return retVal; 249 return ptr;
137 } 250 }
138 251
139 // Allow promotion to bool for conditional statements. 252 // Allow promotion to bool for conditional statements.
140 explicit operator bool() const { return ptr_ != NULL; } 253 explicit operator bool() const { return data_.ptr != nullptr; }
141 254
142 protected: 255 protected:
143 C* ptr_; 256 // Use the empty base class optimization to allow us to have a D
257 // member, while avoiding any space overhead for it when D is an
258 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
259 // discussion of this technique.
260 struct Data : public D {
261 explicit Data(C* ptr_in) : ptr(ptr_in) {}
262 Data(C* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
263 C* ptr;
264 };
265
266 Data data_;
144 }; 267 };
145 268
269 } // namespace internal
270
146 // Implementation for ordinary pointers using delete. 271 // Implementation for ordinary pointers using delete.
147 template <class C> 272 template <class C, class D = DefaultDeleter<C>>
148 class unique_ptr : public unique_ptr_base<C> { 273 class unique_ptr : public internal::unique_ptr_base<C, D> {
149 public: 274 public:
150 using unique_ptr_base<C>::ptr_; 275 // Constructor. Defaults to initializing with nullptr.
276 unique_ptr() : internal::unique_ptr_base<C, D>(nullptr) {}
151 277
152 // Constructor. Defaults to initializing with NULL. There is no way 278 // Constructor. Takes ownership of p.
153 // to create an uninitialized unique_ptr. The input parameter must be 279 explicit unique_ptr(C* p) : internal::unique_ptr_base<C, D>(p) {}
154 // allocated with new (not new[] - see below). 280
155 explicit unique_ptr(C* p = NULL) : unique_ptr_base<C>(p) { } 281 // Constructor. Allows initialization of a stateful deleter.
282 unique_ptr(C* p, const D& d) : internal::unique_ptr_base<C, D>(p, d) {}
Jeffrey Yasskin 2015/09/19 00:00:47 This isn't quite the same as C++11, but it should
Lei Zhang 2015/09/23 00:38:55 Acknowledged.
283
284 // Constructor. Allows construction from a nullptr.
285 unique_ptr(decltype(nullptr)) : internal::unique_ptr_base<C, D>(nullptr) {}
156 286
157 // Move constructor. 287 // Move constructor.
158 unique_ptr(unique_ptr<C>&& that) : unique_ptr_base<C>(nonstd::move(that)) {} 288 unique_ptr(unique_ptr&& that)
289 : internal::unique_ptr_base<C, D>(nonstd::move(that)) {}
159 290
160 // Destructor. If there is a C object, delete it. 291 // operator=. Allows assignment from a nullptr. Deletes the currently owned
161 // We don't need to test ptr_ == NULL because C++ does that for us. 292 // object, if any.
162 ~unique_ptr() { 293 unique_ptr& operator=(decltype(nullptr)) {
163 enum { type_must_be_complete = sizeof(C) }; 294 this->reset();
164 delete ptr_; 295 return *this;
165 } 296 }
166 297
167 // Reset. Deletes the current owned object, if any. 298 private:
168 // Then takes ownership of a new object, if given.
169 // this->reset(this->get()) works.
170 void reset(C* p = NULL) {
171 if (p != ptr_) {
172 enum { type_must_be_complete = sizeof(C) };
173 C* old_ptr = ptr_;
174 ptr_ = p;
175 delete old_ptr;
176 }
177 }
178
179 private:
180 // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't
181 // make sense, and if C2 == C, it still doesn't make sense because you should
182 // never have the same object owned by two different unique_ptrs.
183 template <class C2> bool operator==(unique_ptr<C2> const& p2) const;
184 template <class C2> bool operator!=(unique_ptr<C2> const& p2) const;
185
186 // Disallow evil constructors. It doesn't make sense to make a copy of 299 // Disallow evil constructors. It doesn't make sense to make a copy of
187 // something that's allegedly unique. 300 // something that's allegedly unique.
188 unique_ptr(const unique_ptr&) = delete; 301 unique_ptr(const unique_ptr&) = delete;
189 void operator=(const unique_ptr&) = delete; 302 void operator=(const unique_ptr&) = delete;
190 }; 303 };
191 304
192 // Specialization for arrays using delete[]. 305 // Specialization for arrays using delete[].
193 template <class C> 306 template <class C, class D>
194 class unique_ptr<C[]> : public unique_ptr_base<C> { 307 class unique_ptr<C[], D> : public internal::unique_ptr_base<C, D> {
195 public: 308 public:
196 using unique_ptr_base<C>::ptr_; 309 // Constructor. Defaults to initializing with nullptr.
310 unique_ptr() : internal::unique_ptr_base<C, D>(nullptr) {}
197 311
198 // Constructor. Defaults to initializing with NULL. There is no way 312 // Constructor. Stores the given array. Note that the argument's type
199 // to create an uninitialized unique_ptr. The input parameter must be 313 // must exactly match T*. In particular:
200 // allocated with new[] (not new - see above). 314 // - it cannot be a pointer to a type derived from T, because it is
201 explicit unique_ptr(C* p = NULL) : unique_ptr_base<C>(p) { } 315 // inherently unsafe in the general case to access an array through a
316 // pointer whose dynamic type does not match its static type (eg., if
317 // T and the derived types had different sizes access would be
318 // incorrectly calculated). Deletion is also always undefined
319 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
320 // - it cannot be const-qualified differently from T per unique_ptr spec
321 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
322 // to work around this may use const_cast<const T*>().
323 explicit unique_ptr(C* p) : internal::unique_ptr_base<C, D>(p) {}
Jeffrey Yasskin 2015/09/19 00:00:48 You need to also copy the "template <typename U> e
Lei Zhang 2015/09/23 00:38:55 Done.
324
325 // Constructor. Allows construction from a nullptr.
326 unique_ptr(decltype(nullptr)) : internal::unique_ptr_base<C, D>(nullptr) {}
202 327
203 // Move constructor. 328 // Move constructor.
204 unique_ptr(unique_ptr<C>&& that) : unique_ptr_base<C>(nonstd::move(that)) {} 329 unique_ptr(unique_ptr&& that)
330 : internal::unique_ptr_base<C, D>(nonstd::move(that)) {}
205 331
206 // Destructor. If there is a C object, delete it. 332 // operator=. Allows assignment from a nullptr. Deletes the currently owned
207 // We don't need to test ptr_ == NULL because C++ does that for us. 333 // array, if any.
208 ~unique_ptr() { 334 unique_ptr& operator=(decltype(nullptr)) {
209 enum { type_must_be_complete = sizeof(C) }; 335 this->reset();
210 delete[] ptr_; 336 return *this;
211 }
212
213 // Reset. Deletes the current owned object, if any.
214 // Then takes ownership of a new object, if given.
215 // this->reset(this->get()) works.
216 void reset(C* p = NULL) {
217 if (p != ptr_) {
218 enum { type_must_be_complete = sizeof(C) };
219 C* old_ptr = ptr_;
220 ptr_ = p;
221 delete[] old_ptr;
222 }
223 } 337 }
224 338
225 // Support indexing since it is holding array. 339 // Support indexing since it is holding array.
226 C& operator[] (size_t i) { return ptr_[i]; } 340 C& operator[](size_t i) { return this->data_.ptr[i]; }
227 341
228 private: 342 private:
229 // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't
230 // make sense, and if C2 == C, it still doesn't make sense because you should
231 // never have the same object owned by two different unique_ptrs.
232 template <class C2> bool operator==(unique_ptr<C2> const& p2) const;
233 template <class C2> bool operator!=(unique_ptr<C2> const& p2) const;
234
235 // Disallow evil constructors. It doesn't make sense to make a copy of 343 // Disallow evil constructors. It doesn't make sense to make a copy of
236 // something that's allegedly unique. 344 // something that's allegedly unique.
237 unique_ptr(const unique_ptr&) = delete; 345 unique_ptr(const unique_ptr&) = delete;
238 void operator=(const unique_ptr&) = delete; 346 void operator=(const unique_ptr&) = delete;
239 }; 347 };
240 348
241 // Free functions 349 // Free functions
242 template <class C> 350 template <class C>
243 void swap(unique_ptr<C>& p1, unique_ptr<C>& p2) { 351 void swap(unique_ptr<C>& p1, unique_ptr<C>& p2) {
244 p1.swap(p2); 352 p1.swap(p2);
245 } 353 }
246 354
247 template <class C> 355 template <class C>
248 bool operator==(C* p1, const unique_ptr<C>& p2) { 356 bool operator==(C* p1, const unique_ptr<C>& p2) {
249 return p1 == p2.get(); 357 return p1 == p2.get();
250 } 358 }
251 359
252 template <class C> 360 template <class C>
253 bool operator!=(C* p1, const unique_ptr<C>& p2) { 361 bool operator!=(C* p1, const unique_ptr<C>& p2) {
254 return p1 != p2.get(); 362 return p1 != p2.get();
255 } 363 }
256 364
365 template <typename T>
366 std::ostream& operator<<(std::ostream& out, const unique_ptr<T>& p) {
367 return out << p.get();
368 }
369
257 } // namespace nonstd 370 } // namespace nonstd
258 371
259 #endif // NONSTD_UNIQUE_PTR_H_ 372 #endif // NONSTD_UNIQUE_PTR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698