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

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, steal more code Created 5 years, 2 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 <ostream>
77
78 #include "template_util.h"
79
76 namespace nonstd { 80 namespace nonstd {
77 81
78 // Replacement for move, but doesn't allow things that are already 82 // Replacement for move, but doesn't allow things that are already
79 // rvalue references. 83 // rvalue references.
80 template <class T> 84 template <class T>
81 T&& move(T& t) { 85 T&& move(T& t) {
82 return static_cast<T&&>(t); 86 return static_cast<T&&>(t);
83 } 87 }
84 88
89 // Function object which deletes its parameter, which must be a pointer.
90 // If C is an array type, invokes 'delete[]' on the parameter; otherwise,
91 // invokes 'delete'. The default deleter for unique_ptr<T>.
92 template <class T>
93 struct DefaultDeleter {
94 DefaultDeleter() {}
95 template <typename U>
96 DefaultDeleter(const DefaultDeleter<U>& other) {
97 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
98 // if U* is implicitly convertible to T* and U is not an array type.
99 //
100 // Correct implementation should use SFINAE to disable this
101 // constructor. However, since there are no other 1-argument constructors,
102 // using a static_assert() based on is_convertible<> and requiring
103 // complete types is simpler and will cause compile failures for equivalent
104 // misuses.
105 //
106 // Note, the is_convertible<U*, T*> check also ensures that U is not an
107 // array. T is guaranteed to be a non-array, so any U* where U is an array
108 // cannot convert to T*.
109 enum { T_must_be_complete = sizeof(T) };
110 enum { U_must_be_complete = sizeof(U) };
111 static_assert((pdfium::base::is_convertible<U*, T*>::value),
112 "U_ptr_must_implicitly_convert_to_T_ptr");
113 }
114 inline void operator()(T* ptr) const {
115 enum { type_must_be_complete = sizeof(T) };
116 delete ptr;
117 }
118 };
119
120 // Specialization of DefaultDeleter for array types.
121 template <class T>
122 struct DefaultDeleter<T[]> {
123 inline void operator()(T* ptr) const {
124 enum { type_must_be_complete = sizeof(T) };
125 delete[] ptr;
126 }
127
128 private:
129 // Disable this operator for any U != T because it is undefined to execute
130 // an array delete when the static type of the array mismatches the dynamic
131 // type.
132 //
133 // References:
134 // C++98 [expr.delete]p3
135 // http://cplusplus.github.com/LWG/lwg-defects.html#938
136 template <typename U>
137 void operator()(U* array) const;
138 };
139
140 template <class T, int n>
141 struct DefaultDeleter<T[n]> {
142 // Never allow someone to declare something like unique_ptr<int[10]>.
143 static_assert(sizeof(T) == -1, "do_not_use_array_with_size_as_type");
144 };
145
146 namespace internal {
147
85 // Common implementation for both pointers to elements and pointers to 148 // Common implementation for both pointers to elements and pointers to
86 // arrays. These are differentiated below based on the need to invoke 149 // arrays. These are differentiated below based on the need to invoke
87 // delete vs. delete[] as appropriate. 150 // delete vs. delete[] as appropriate.
88 template <class C> 151 template <class C, class D>
89 class unique_ptr_base { 152 class unique_ptr_base {
90 public: 153 public:
91
92 // The element type 154 // The element type
93 typedef C element_type; 155 typedef C element_type;
94 156
95 explicit unique_ptr_base(C* p) : ptr_(p) { } 157 explicit unique_ptr_base(C* p) : data_(p) {}
158
159 // Initializer for deleters that have data parameters.
160 unique_ptr_base(C* p, const D& d) : data_(p, d) {}
96 161
97 // Move constructor. 162 // Move constructor.
98 unique_ptr_base(unique_ptr_base<C>&& that) { 163 unique_ptr_base(unique_ptr_base<C, D>&& that)
99 ptr_ = that.ptr_; 164 : data_(that.release(), that.get_deleter()) {}
100 that.ptr_ = nullptr; 165
166 ~unique_ptr_base() {
167 enum { type_must_be_complete = sizeof(C) };
168 if (data_.ptr != nullptr) {
169 // Not using get_deleter() saves one function call in non-optimized
170 // builds.
171 static_cast<D&>(data_)(data_.ptr);
172 }
101 } 173 }
102 174
103 // Accessors to get the owned object. 175 void reset(C* p = nullptr) {
104 // operator* and operator-> will assert() if there is no current object. 176 // Note that running data_.ptr = p can lead to undefined behavior if
Jeffrey Yasskin 2015/09/23 00:53:34 I forgot to mention this: you can go straight to t
Lei Zhang 2015/09/23 01:11:30 Done.
105 C& operator*() const { 177 // get_deleter()(get()) deletes this. In order to prevent this, reset()
106 assert(ptr_ != NULL); 178 // should update the stored pointer before deleting its old value.
107 return *ptr_; 179 //
180 // However, changing reset() to use that behavior may cause current code to
181 // break in unexpected ways. If the destruction of the owned object
182 // dereferences the unique_ptr when it is destroyed by a call to reset(),
183 // then it will incorrectly dispatch calls to |p| rather than the original
184 // value of |data_.ptr|.
185 //
186 // During the transition period, set the stored pointer to nullptr while
187 // deleting the object. Eventually, this safety check will be removed to
188 // prevent the scenario initially described from occuring and
189 // http://crbug.com/176091 can be closed.
190 C* old = data_.ptr;
191 data_.ptr = nullptr;
192 if (old != nullptr)
193 static_cast<D&>(data_)(old);
194 data_.ptr = p;
108 } 195 }
109 C* operator->() const { 196
110 assert(ptr_ != NULL); 197 C* get() const { return data_.ptr; }
111 return ptr_; 198 D& get_deleter() { return data_; }
112 } 199 const D& get_deleter() const { return data_; }
113 C* get() const { return ptr_; }
114 200
115 // Comparison operators. 201 // Comparison operators.
116 // These return whether two unique_ptr refer to the same object, not just to 202 // These return whether two unique_ptr refer to the same object, not just to
117 // two different but equal objects. 203 // two different but equal objects.
118 bool operator==(C* p) const { return ptr_ == p; } 204 bool operator==(C* p) const { return data_.ptr == p; }
119 bool operator!=(C* p) const { return ptr_ != p; } 205 bool operator!=(C* p) const { return data_.ptr != p; }
120 206
121 // Swap two scoped pointers. 207 // Swap two unique pointers.
122 void swap(unique_ptr_base& p2) { 208 void swap(unique_ptr_base& p2) {
123 C* tmp = ptr_; 209 Data tmp = data_;
124 ptr_ = p2.ptr_; 210 data_ = p2.data_;
125 p2.ptr_ = tmp; 211 p2.data_ = tmp;
126 } 212 }
127 213
128 // Release a pointer. 214 // Release a pointer.
129 // The return value is the current pointer held by this object. 215 // The return value is the current pointer held by this object.
130 // If this object holds a NULL pointer, the return value is NULL. 216 // If this object holds a NULL pointer, the return value is NULL.
131 // After this operation, this object will hold a NULL pointer, 217 // After this operation, this object will hold a NULL pointer,
132 // and will not own the object any more. 218 // and will not own the object any more.
133 C* release() { 219 C* release() {
134 C* retVal = ptr_; 220 C* ptr = data_.ptr;
135 ptr_ = NULL; 221 data_.ptr = nullptr;
136 return retVal; 222 return ptr;
137 } 223 }
138 224
139 // Allow promotion to bool for conditional statements. 225 // Allow promotion to bool for conditional statements.
140 explicit operator bool() const { return ptr_ != NULL; } 226 explicit operator bool() const { return data_.ptr != nullptr; }
141 227
142 protected: 228 protected:
143 C* ptr_; 229 // Use the empty base class optimization to allow us to have a D
230 // member, while avoiding any space overhead for it when D is an
231 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
232 // discussion of this technique.
233 struct Data : public D {
234 explicit Data(C* ptr_in) : ptr(ptr_in) {}
235 Data(C* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
236 C* ptr;
237 };
238
239 Data data_;
144 }; 240 };
145 241
242 } // namespace internal
243
146 // Implementation for ordinary pointers using delete. 244 // Implementation for ordinary pointers using delete.
147 template <class C> 245 template <class C, class D = DefaultDeleter<C>>
148 class unique_ptr : public unique_ptr_base<C> { 246 class unique_ptr : public internal::unique_ptr_base<C, D> {
149 public: 247 public:
150 using unique_ptr_base<C>::ptr_; 248 // Constructor. Defaults to initializing with nullptr.
249 unique_ptr() : internal::unique_ptr_base<C, D>(nullptr) {}
151 250
152 // Constructor. Defaults to initializing with NULL. There is no way 251 // Constructor. Takes ownership of p.
153 // to create an uninitialized unique_ptr. The input parameter must be 252 explicit unique_ptr(C* p) : internal::unique_ptr_base<C, D>(p) {}
154 // allocated with new (not new[] - see below). 253
155 explicit unique_ptr(C* p = NULL) : unique_ptr_base<C>(p) { } 254 // Constructor. Allows initialization of a stateful deleter.
255 unique_ptr(C* p, const D& d) : internal::unique_ptr_base<C, D>(p, d) {}
256
257 // Constructor. Allows construction from a nullptr.
258 unique_ptr(decltype(nullptr)) : internal::unique_ptr_base<C, D>(nullptr) {}
156 259
157 // Move constructor. 260 // Move constructor.
158 unique_ptr(unique_ptr<C>&& that) : unique_ptr_base<C>(nonstd::move(that)) {} 261 unique_ptr(unique_ptr&& that)
262 : internal::unique_ptr_base<C, D>(nonstd::move(that)) {}
159 263
160 // Destructor. If there is a C object, delete it. 264 // 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. 265 // object, if any.
162 ~unique_ptr() { 266 unique_ptr& operator=(decltype(nullptr)) {
163 enum { type_must_be_complete = sizeof(C) }; 267 this->reset();
164 delete ptr_; 268 return *this;
165 }
166
167 // Reset. Deletes the current owned object, if any.
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 } 269 }
178 270
179 // Move assignment. 271 // Move assignment.
180 unique_ptr<C>& operator=(unique_ptr<C>&& that) { 272 unique_ptr<C>& operator=(unique_ptr<C>&& that) {
181 if (that.ptr_ != ptr_) 273 if (that.data_.ptr != this->data_.ptr)
Jeffrey Yasskin 2015/09/23 00:53:34 You can remove this check: a self-reset will natur
Lei Zhang 2015/09/23 01:11:30 Done.
182 reset(that.release()); 274 this->reset(that.release());
183 return *this; 275 return *this;
184 } 276 }
185 277
186 private: 278 // Accessors to get the owned object.
187 // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't 279 // operator* and operator-> will assert() if there is no current object.
188 // make sense, and if C2 == C, it still doesn't make sense because you should 280 C& operator*() const {
189 // never have the same object owned by two different unique_ptrs. 281 assert(this->data_.ptr != nullptr);
190 template <class C2> bool operator==(unique_ptr<C2> const& p2) const; 282 return *this->data_.ptr;
191 template <class C2> bool operator!=(unique_ptr<C2> const& p2) const; 283 }
284 C* operator->() const {
285 assert(this->data_.ptr != nullptr);
286 return this->data_.ptr;
287 }
192 288
289 // Comparison operators.
290 // These return whether two unique_ptr refer to the same object, not just to
291 // two different but equal objects.
292 bool operator==(const C* p) const { return this->get() == p; }
293 bool operator!=(const C* p) const { return this->get() != p; }
294
295 private:
193 // Disallow evil constructors. It doesn't make sense to make a copy of 296 // Disallow evil constructors. It doesn't make sense to make a copy of
194 // something that's allegedly unique. 297 // something that's allegedly unique.
195 unique_ptr(const unique_ptr&) = delete; 298 unique_ptr(const unique_ptr&) = delete;
196 void operator=(const unique_ptr&) = delete; 299 void operator=(const unique_ptr&) = delete;
300
301 // Forbid comparison of unique_ptr types. If U != C, it totally
302 // doesn't make sense, and if U == C, it still doesn't make sense
303 // because you should never have the same object owned by two different
304 // unique_ptrs.
305 template <class U>
306 bool operator==(unique_ptr<U> const& p2) const;
307 template <class U>
308 bool operator!=(unique_ptr<U> const& p2) const;
197 }; 309 };
198 310
199 // Specialization for arrays using delete[]. 311 // Specialization for arrays using delete[].
200 template <class C> 312 template <class C, class D>
201 class unique_ptr<C[]> : public unique_ptr_base<C> { 313 class unique_ptr<C[], D> : public internal::unique_ptr_base<C, D> {
202 public: 314 public:
203 using unique_ptr_base<C>::ptr_; 315 // Constructor. Defaults to initializing with nullptr.
316 unique_ptr() : internal::unique_ptr_base<C, D>(nullptr) {}
204 317
205 // Constructor. Defaults to initializing with NULL. There is no way 318 // Constructor. Stores the given array. Note that the argument's type
206 // to create an uninitialized unique_ptr. The input parameter must be 319 // must exactly match T*. In particular:
207 // allocated with new[] (not new - see above). 320 // - it cannot be a pointer to a type derived from T, because it is
208 explicit unique_ptr(C* p = NULL) : unique_ptr_base<C>(p) { } 321 // inherently unsafe in the general case to access an array through a
322 // pointer whose dynamic type does not match its static type (eg., if
323 // T and the derived types had different sizes access would be
324 // incorrectly calculated). Deletion is also always undefined
325 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
326 // - it cannot be const-qualified differently from T per unique_ptr spec
327 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
328 // to work around this may use const_cast<const T*>().
329 explicit unique_ptr(C* p) : internal::unique_ptr_base<C, D>(p) {}
330
331 // Constructor. Allows construction from a nullptr.
332 unique_ptr(decltype(nullptr)) : internal::unique_ptr_base<C, D>(nullptr) {}
209 333
210 // Move constructor. 334 // Move constructor.
211 unique_ptr(unique_ptr<C>&& that) : unique_ptr_base<C>(nonstd::move(that)) {} 335 unique_ptr(unique_ptr&& that)
336 : internal::unique_ptr_base<C, D>(nonstd::move(that)) {}
212 337
213 // Destructor. If there is a C object, delete it. 338 // operator=. Allows assignment from a nullptr. Deletes the currently owned
214 // We don't need to test ptr_ == NULL because C++ does that for us. 339 // array, if any.
215 ~unique_ptr() { 340 unique_ptr& operator=(decltype(nullptr)) {
216 enum { type_must_be_complete = sizeof(C) }; 341 this->reset();
217 delete[] ptr_; 342 return *this;
218 }
219
220 // Reset. Deletes the current owned object, if any.
221 // Then takes ownership of a new object, if given.
222 // this->reset(this->get()) works.
223 void reset(C* p = NULL) {
224 if (p != ptr_) {
225 enum { type_must_be_complete = sizeof(C) };
226 C* old_ptr = ptr_;
227 ptr_ = p;
228 delete[] old_ptr;
229 }
230 } 343 }
231 344
232 // Move assignment. 345 // Move assignment.
233 unique_ptr<C>& operator=(unique_ptr<C>&& that) { 346 unique_ptr<C>& operator=(unique_ptr<C>&& that) {
234 if (that.ptr_ != ptr_) 347 if (that.data_.ptr != this->data_.ptr)
Jeffrey Yasskin 2015/09/23 00:53:35 Same here.
Lei Zhang 2015/09/23 01:11:30 Done.
235 reset(that.release()); 348 this->reset(that.release());
236 return *this; 349 return *this;
237 } 350 }
238 351
352 // Reset. Deletes the currently owned array, if any.
353 // Then takes ownership of a new object, if given.
354 void reset(C* array = nullptr) {
355 static_cast<internal::unique_ptr_base<C, D>*>(this)->reset(array);
356 }
357
239 // Support indexing since it is holding array. 358 // Support indexing since it is holding array.
240 C& operator[] (size_t i) { return ptr_[i]; } 359 C& operator[](size_t i) { return this->data_.ptr[i]; }
241 360
242 private: 361 // Comparison operators.
243 // Forbid comparison of unique_ptr types. If C2 != C, it totally doesn't 362 // These return whether two unique_ptr refer to the same object, not just to
244 // make sense, and if C2 == C, it still doesn't make sense because you should 363 // two different but equal objects.
245 // never have the same object owned by two different unique_ptrs. 364 bool operator==(C* array) const { return this->get() == array; }
246 template <class C2> bool operator==(unique_ptr<C2> const& p2) const; 365 bool operator!=(C* array) const { return this->get() != array; }
247 template <class C2> bool operator!=(unique_ptr<C2> const& p2) const; 366
367 private:
368 // Disable initialization from any type other than element_type*, by
369 // providing a constructor that matches such an initialization, but is
370 // private and has no definition. This is disabled because it is not safe to
371 // call delete[] on an array whose static type does not match its dynamic
372 // type.
373 template <typename U>
374 explicit unique_ptr(U* array);
375 explicit unique_ptr(int disallow_construction_from_null);
376
377 // Disable reset() from any type other than element_type*, for the same
378 // reasons as the constructor above.
379 template <typename U>
380 void reset(U* array);
381 void reset(int disallow_reset_from_null);
248 382
249 // Disallow evil constructors. It doesn't make sense to make a copy of 383 // Disallow evil constructors. It doesn't make sense to make a copy of
250 // something that's allegedly unique. 384 // something that's allegedly unique.
251 unique_ptr(const unique_ptr&) = delete; 385 unique_ptr(const unique_ptr&) = delete;
252 void operator=(const unique_ptr&) = delete; 386 void operator=(const unique_ptr&) = delete;
387
388 // Forbid comparison of unique_ptr types. If U != C, it totally
389 // doesn't make sense, and if U == C, it still doesn't make sense
390 // because you should never have the same object owned by two different
391 // unique_ptrs.
392 template <class U>
393 bool operator==(unique_ptr<U> const& p2) const;
394 template <class U>
395 bool operator!=(unique_ptr<U> const& p2) const;
253 }; 396 };
254 397
255 // Free functions 398 // Free functions
256 template <class C> 399 template <class C>
257 void swap(unique_ptr<C>& p1, unique_ptr<C>& p2) { 400 void swap(unique_ptr<C>& p1, unique_ptr<C>& p2) {
258 p1.swap(p2); 401 p1.swap(p2);
259 } 402 }
260 403
261 template <class C> 404 template <class C>
262 bool operator==(C* p1, const unique_ptr<C>& p2) { 405 bool operator==(C* p1, const unique_ptr<C>& p2) {
263 return p1 == p2.get(); 406 return p1 == p2.get();
264 } 407 }
265 408
266 template <class C> 409 template <class C>
267 bool operator!=(C* p1, const unique_ptr<C>& p2) { 410 bool operator!=(C* p1, const unique_ptr<C>& p2) {
268 return p1 != p2.get(); 411 return p1 != p2.get();
269 } 412 }
270 413
414 template <typename T>
415 std::ostream& operator<<(std::ostream& out, const unique_ptr<T>& p) {
416 return out << p.get();
417 }
418
271 } // namespace nonstd 419 } // namespace nonstd
272 420
273 #endif // NONSTD_UNIQUE_PTR_H_ 421 #endif // NONSTD_UNIQUE_PTR_H_
OLDNEW
« no previous file with comments | « core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp ('k') | third_party/base/nonstd_unique_ptr_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698