blob: 3b3301fbea4a9663805fadfc337c220ccc414e9f [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +000011// Borrowed from Chromium's src/base/memory/scoped_ptr.h.
12
13// Scopers help you manage ownership of a pointer, helping you easily manage a
14// pointer within a scope, and automatically destroying the pointer at the end
15// of a scope. There are two main classes you will use, which correspond to the
16// operators new/delete and new[]/delete[].
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000017//
18// Example usage (scoped_ptr<T>):
19// {
20// scoped_ptr<Foo> foo(new Foo("wee"));
21// } // foo goes out of scope, releasing the pointer with it.
22//
23// {
24// scoped_ptr<Foo> foo; // No pointer managed.
25// foo.reset(new Foo("wee")); // Now a pointer is managed.
26// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
27// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
28// foo->Method(); // Foo::Method() called.
29// foo.get()->Method(); // Foo::Method() called.
30// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
31// // manages a pointer.
32// foo.reset(new Foo("wee4")); // foo manages a pointer again.
33// foo.reset(); // Foo("wee4") destroyed, foo no longer
34// // manages a pointer.
35// } // foo wasn't managing a pointer, so nothing was destroyed.
36//
37// Example usage (scoped_ptr<T[]>):
38// {
39// scoped_ptr<Foo[]> foo(new Foo[100]);
40// foo.get()->Method(); // Foo::Method on the 0th element.
41// foo[10].Method(); // Foo::Method on the 10th element.
42// }
43//
44// These scopers also implement part of the functionality of C++11 unique_ptr
kwiberg0eb15ed2015-12-17 03:04:15 -080045// in that they are "movable but not copyable." You can use the scopers in the
46// parameter and return types of functions to signify ownership transfer in to
47// and out of a function. When calling a function that has a scoper as the
48// argument type, it must be called with the result of calling std::move on an
49// analogous scoper, or another function that generates a temporary; passing by
50// copy will NOT work. Here is an example using scoped_ptr:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051//
52// void TakesOwnership(scoped_ptr<Foo> arg) {
53// // Do something with arg
54// }
55// scoped_ptr<Foo> CreateFoo() {
kwiberg0eb15ed2015-12-17 03:04:15 -080056// // No need for calling std::move because we are constructing a temporary
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057// // for the return value.
58// return scoped_ptr<Foo>(new Foo("new"));
59// }
60// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
kwiberg0eb15ed2015-12-17 03:04:15 -080061// return std::move(arg);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062// }
63//
64// {
65// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
kwiberg0eb15ed2015-12-17 03:04:15 -080066// TakesOwnership(std::move(ptr)); // ptr no longer owns Foo("yay").
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000067// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
68// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
kwiberg0eb15ed2015-12-17 03:04:15 -080069// PassThru(std::move(ptr2)); // ptr2 is correspondingly nullptr.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070// }
71//
kwiberg0eb15ed2015-12-17 03:04:15 -080072// Notice that if you do not call std::move when returning from PassThru(), or
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000073// when invoking TakesOwnership(), the code will not compile because scopers
74// are not copyable; they only implement move semantics which require calling
kwiberg0eb15ed2015-12-17 03:04:15 -080075// std::move to signify a destructive transfer of state. CreateFoo() is
76// different though because we are constructing a temporary on the return line
77// and thus can avoid needing to call std::move.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000078
79#ifndef WEBRTC_BASE_SCOPED_PTR_H__
80#define WEBRTC_BASE_SCOPED_PTR_H__
81
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +000082// This is an implementation designed to match the anticipated future TR2
83// implementation of the scoped_ptr class.
84
85#include <assert.h>
86#include <stddef.h>
87#include <stdlib.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088
89#include <algorithm> // For std::swap().
90
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +000091#include "webrtc/base/constructormagic.h"
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +000092#include "webrtc/base/template_util.h"
93#include "webrtc/typedefs.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000094
95namespace rtc {
96
97// Function object which deletes its parameter, which must be a pointer.
98// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
99// invokes 'delete'. The default deleter for scoped_ptr<T>.
100template <class T>
101struct DefaultDeleter {
102 DefaultDeleter() {}
103 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
104 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
105 // if U* is implicitly convertible to T* and U is not an array type.
106 //
107 // Correct implementation should use SFINAE to disable this
108 // constructor. However, since there are no other 1-argument constructors,
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000109 // using a static_assert based on is_convertible<> and requiring
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000110 // complete types is simpler and will cause compile failures for equivalent
111 // misuses.
112 //
113 // Note, the is_convertible<U*, T*> check also ensures that U is not an
114 // array. T is guaranteed to be a non-array, so any U* where U is an array
115 // cannot convert to T*.
116 enum { T_must_be_complete = sizeof(T) };
117 enum { U_must_be_complete = sizeof(U) };
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000118 static_assert(rtc::is_convertible<U*, T*>::value,
119 "U* must implicitly convert to T*");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000120 }
121 inline void operator()(T* ptr) const {
122 enum { type_must_be_complete = sizeof(T) };
123 delete ptr;
124 }
125};
126
127// Specialization of DefaultDeleter for array types.
128template <class T>
129struct DefaultDeleter<T[]> {
130 inline void operator()(T* ptr) const {
131 enum { type_must_be_complete = sizeof(T) };
132 delete[] ptr;
133 }
134
135 private:
136 // Disable this operator for any U != T because it is undefined to execute
137 // an array delete when the static type of the array mismatches the dynamic
138 // type.
139 //
140 // References:
141 // C++98 [expr.delete]p3
142 // http://cplusplus.github.com/LWG/lwg-defects.html#938
143 template <typename U> void operator()(U* array) const;
144};
145
146template <class T, int n>
147struct DefaultDeleter<T[n]> {
148 // Never allow someone to declare something like scoped_ptr<int[10]>.
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000149 static_assert(sizeof(T) == -1, "do not use array with size as type");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000150};
151
152// Function object which invokes 'free' on its parameter, which must be
153// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
154//
155// scoped_ptr<int, rtc::FreeDeleter> foo_ptr(
156// static_cast<int*>(malloc(sizeof(int))));
157struct FreeDeleter {
158 inline void operator()(void* ptr) const {
159 free(ptr);
160 }
161};
162
163namespace internal {
164
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000165template <typename T>
166struct ShouldAbortOnSelfReset {
167 template <typename U>
168 static rtc::internal::NoType Test(const typename U::AllowSelfReset*);
169
170 template <typename U>
171 static rtc::internal::YesType Test(...);
172
173 static const bool value =
174 sizeof(Test<T>(0)) == sizeof(rtc::internal::YesType);
175};
176
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000177// Minimal implementation of the core logic of scoped_ptr, suitable for
178// reuse in both scoped_ptr and its specializations.
179template <class T, class D>
180class scoped_ptr_impl {
181 public:
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000182 explicit scoped_ptr_impl(T* p) : data_(p) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000183
184 // Initializer for deleters that have data parameters.
185 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
186
187 // Templated constructor that destructively takes the value from another
188 // scoped_ptr_impl.
189 template <typename U, typename V>
190 scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
191 : data_(other->release(), other->get_deleter()) {
192 // We do not support move-only deleters. We could modify our move
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000193 // emulation to have rtc::subtle::move() and rtc::subtle::forward()
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000194 // functions that are imperfect emulations of their C++11 equivalents,
195 // but until there's a requirement, just assume deleters are copyable.
196 }
197
198 template <typename U, typename V>
199 void TakeState(scoped_ptr_impl<U, V>* other) {
200 // See comment in templated constructor above regarding lack of support
201 // for move-only deleters.
202 reset(other->release());
203 get_deleter() = other->get_deleter();
204 }
205
206 ~scoped_ptr_impl() {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000207 if (data_.ptr != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000208 // Not using get_deleter() saves one function call in non-optimized
209 // builds.
210 static_cast<D&>(data_)(data_.ptr);
211 }
212 }
213
214 void reset(T* p) {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000215 // This is a self-reset, which is no longer allowed for default deleters:
216 // https://crbug.com/162971
217 assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000218
219 // Note that running data_.ptr = p can lead to undefined behavior if
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000220 // get_deleter()(get()) deletes this. In order to prevent this, reset()
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000221 // should update the stored pointer before deleting its old value.
222 //
223 // However, changing reset() to use that behavior may cause current code to
224 // break in unexpected ways. If the destruction of the owned object
225 // dereferences the scoped_ptr when it is destroyed by a call to reset(),
226 // then it will incorrectly dispatch calls to |p| rather than the original
227 // value of |data_.ptr|.
228 //
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000229 // During the transition period, set the stored pointer to nullptr while
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000230 // deleting the object. Eventually, this safety check will be removed to
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000231 // prevent the scenario initially described from occurring and
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000232 // http://crbug.com/176091 can be closed.
233 T* old = data_.ptr;
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000234 data_.ptr = nullptr;
235 if (old != nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000236 static_cast<D&>(data_)(old);
237 data_.ptr = p;
238 }
239
240 T* get() const { return data_.ptr; }
241
242 D& get_deleter() { return data_; }
243 const D& get_deleter() const { return data_; }
244
245 void swap(scoped_ptr_impl& p2) {
246 // Standard swap idiom: 'using std::swap' ensures that std::swap is
247 // present in the overload set, but we call swap unqualified so that
248 // any more-specific overloads can be used, if available.
249 using std::swap;
250 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
251 swap(data_.ptr, p2.data_.ptr);
252 }
253
254 T* release() {
255 T* old_ptr = data_.ptr;
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000256 data_.ptr = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000257 return old_ptr;
258 }
259
260 T** accept() {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000261 reset(nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262 return &(data_.ptr);
263 }
264
265 T** use() {
266 return &(data_.ptr);
267 }
268
269 private:
270 // Needed to allow type-converting constructor.
271 template <typename U, typename V> friend class scoped_ptr_impl;
272
273 // Use the empty base class optimization to allow us to have a D
274 // member, while avoiding any space overhead for it when D is an
275 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
276 // discussion of this technique.
277 struct Data : public D {
278 explicit Data(T* ptr_in) : ptr(ptr_in) {}
279 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
280 T* ptr;
281 };
282
283 Data data_;
284
henrikg3c089d72015-09-16 05:37:44 -0700285 RTC_DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000286};
287
288} // namespace internal
289
290// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
291// automatically deletes the pointer it holds (if any).
292// That is, scoped_ptr<T> owns the T object that it points to.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000293// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
294// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000295// dereference it, you get the thread safety guarantees of T.
296//
297// The size of scoped_ptr is small. On most compilers, when using the
298// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
299// increase the size proportional to whatever state they need to have. See
300// comments inside scoped_ptr_impl<> for details.
301//
302// Current implementation targets having a strict subset of C++11's
303// unique_ptr<> features. Known deficiencies include not supporting move-only
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000304// deleters, function pointers as deleters, and deleters with reference
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000305// types.
306template <class T, class D = rtc::DefaultDeleter<T> >
307class scoped_ptr {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000308
309 // TODO(ajm): If we ever import RefCountedBase, this check needs to be
310 // enabled.
311 //static_assert(rtc::internal::IsNotRefCounted<T>::value,
312 // "T is refcounted type and needs scoped refptr");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000313
314 public:
315 // The element and deleter types.
316 typedef T element_type;
317 typedef D deleter_type;
318
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000319 // Constructor. Defaults to initializing with nullptr.
320 scoped_ptr() : impl_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000321
322 // Constructor. Takes ownership of p.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000323 explicit scoped_ptr(element_type* p) : impl_(p) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000324
325 // Constructor. Allows initialization of a stateful deleter.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000326 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
327
328 // Constructor. Allows construction from a nullptr.
329 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000330
331 // Constructor. Allows construction from a scoped_ptr rvalue for a
332 // convertible type and deleter.
333 //
334 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
335 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
336 // has different post-conditions if D is a reference type. Since this
337 // implementation does not support deleters with reference type,
338 // we do not need a separate move constructor allowing us to avoid one
339 // use of SFINAE. You only need to care about this if you modify the
340 // implementation of scoped_ptr.
341 template <typename U, typename V>
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000342 scoped_ptr(scoped_ptr<U, V>&& other)
343 : impl_(&other.impl_) {
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000344 static_assert(!rtc::is_array<U>::value, "U cannot be an array");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 }
346
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000347 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
348 // type and deleter.
349 //
350 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
351 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
352 // form has different requirements on for move-only Deleters. Since this
353 // implementation does not support move-only Deleters, we do not need a
354 // separate move assignment operator allowing us to avoid one use of SFINAE.
355 // You only need to care about this if you modify the implementation of
356 // scoped_ptr.
357 template <typename U, typename V>
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000358 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) {
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000359 static_assert(!rtc::is_array<U>::value, "U cannot be an array");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000360 impl_.TakeState(&rhs.impl_);
361 return *this;
362 }
363
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000364 // operator=. Allows assignment from a nullptr. Deletes the currently owned
365 // object, if any.
366 scoped_ptr& operator=(decltype(nullptr)) {
367 reset();
368 return *this;
369 }
370
Karl Wiberga8e285d2015-04-22 19:44:19 +0200371 // Deleted copy constructor and copy assignment, to make the type move-only.
372 scoped_ptr(const scoped_ptr& other) = delete;
373 scoped_ptr& operator=(const scoped_ptr& other) = delete;
374
375 // Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
376 scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
377
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000378 // Reset. Deletes the currently owned object, if any.
379 // Then takes ownership of a new object, if given.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000380 void reset(element_type* p = nullptr) { impl_.reset(p); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000381
382 // Accessors to get the owned object.
383 // operator* and operator-> will assert() if there is no current object.
384 element_type& operator*() const {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000385 assert(impl_.get() != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000386 return *impl_.get();
387 }
388 element_type* operator->() const {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000389 assert(impl_.get() != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000390 return impl_.get();
391 }
392 element_type* get() const { return impl_.get(); }
393
394 // Access to the deleter.
395 deleter_type& get_deleter() { return impl_.get_deleter(); }
396 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
397
398 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
399 // implicitly convertible to a real bool (which is dangerous).
400 //
401 // Note that this trick is only safe when the == and != operators
402 // are declared explicitly, as otherwise "scoped_ptr1 ==
403 // scoped_ptr2" will compile but do the wrong thing (i.e., convert
404 // to Testable and then do the comparison).
405 private:
406 typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
407 scoped_ptr::*Testable;
408
409 public:
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000410 operator Testable() const {
411 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
412 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000413
414 // Comparison operators.
415 // These return whether two scoped_ptr refer to the same object, not just to
416 // two different but equal objects.
417 bool operator==(const element_type* p) const { return impl_.get() == p; }
418 bool operator!=(const element_type* p) const { return impl_.get() != p; }
419
420 // Swap two scoped pointers.
421 void swap(scoped_ptr& p2) {
422 impl_.swap(p2.impl_);
423 }
424
425 // Release a pointer.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000426 // The return value is the current pointer held by this object. If this object
427 // holds a nullptr, the return value is nullptr. After this operation, this
428 // object will hold a nullptr, and will not own the object any more.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000429 element_type* release() WARN_UNUSED_RESULT {
430 return impl_.release();
431 }
432
433 // Delete the currently held pointer and return a pointer
434 // to allow overwriting of the current pointer address.
435 element_type** accept() WARN_UNUSED_RESULT {
436 return impl_.accept();
437 }
438
439 // Return a pointer to the current pointer address.
440 element_type** use() WARN_UNUSED_RESULT {
441 return impl_.use();
442 }
443
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000444 private:
445 // Needed to reach into |impl_| in the constructor.
446 template <typename U, typename V> friend class scoped_ptr;
447 rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
448
449 // Forbidden for API compatibility with std::unique_ptr.
450 explicit scoped_ptr(int disallow_construction_from_null);
451
452 // Forbid comparison of scoped_ptr types. If U != T, it totally
453 // doesn't make sense, and if U == T, it still doesn't make sense
454 // because you should never have the same object owned by two different
455 // scoped_ptrs.
456 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
457 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
458};
459
460template <class T, class D>
461class scoped_ptr<T[], D> {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000462 public:
463 // The element and deleter types.
464 typedef T element_type;
465 typedef D deleter_type;
466
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000467 // Constructor. Defaults to initializing with nullptr.
468 scoped_ptr() : impl_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000469
470 // Constructor. Stores the given array. Note that the argument's type
471 // must exactly match T*. In particular:
472 // - it cannot be a pointer to a type derived from T, because it is
473 // inherently unsafe in the general case to access an array through a
474 // pointer whose dynamic type does not match its static type (eg., if
475 // T and the derived types had different sizes access would be
476 // incorrectly calculated). Deletion is also always undefined
477 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000478 // - it cannot be const-qualified differently from T per unique_ptr spec
479 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
480 // to work around this may use implicit_cast<const T*>().
481 // However, because of the first bullet in this comment, users MUST
482 // NOT use implicit_cast<Base*>() to upcast the static type of the array.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000483 explicit scoped_ptr(element_type* array) : impl_(array) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000484
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000485 // Constructor. Allows construction from a nullptr.
486 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000487
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000488 // Constructor. Allows construction from a scoped_ptr rvalue.
489 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
490
491 // operator=. Allows assignment from a scoped_ptr rvalue.
492 scoped_ptr& operator=(scoped_ptr&& rhs) {
493 impl_.TakeState(&rhs.impl_);
494 return *this;
495 }
496
497 // operator=. Allows assignment from a nullptr. Deletes the currently owned
498 // array, if any.
499 scoped_ptr& operator=(decltype(nullptr)) {
500 reset();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000501 return *this;
502 }
503
Karl Wiberga8e285d2015-04-22 19:44:19 +0200504 // Deleted copy constructor and copy assignment, to make the type move-only.
505 scoped_ptr(const scoped_ptr& other) = delete;
506 scoped_ptr& operator=(const scoped_ptr& other) = delete;
507
508 // Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
509 scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
510
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000511 // Reset. Deletes the currently owned array, if any.
512 // Then takes ownership of a new object, if given.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000513 void reset(element_type* array = nullptr) { impl_.reset(array); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000514
515 // Accessors to get the owned array.
516 element_type& operator[](size_t i) const {
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000517 assert(impl_.get() != nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000518 return impl_.get()[i];
519 }
520 element_type* get() const { return impl_.get(); }
521
522 // Access to the deleter.
523 deleter_type& get_deleter() { return impl_.get_deleter(); }
524 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
525
526 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
527 // implicitly convertible to a real bool (which is dangerous).
528 private:
529 typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
530 scoped_ptr::*Testable;
531
532 public:
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000533 operator Testable() const {
534 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
535 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000536
537 // Comparison operators.
538 // These return whether two scoped_ptr refer to the same object, not just to
539 // two different but equal objects.
540 bool operator==(element_type* array) const { return impl_.get() == array; }
541 bool operator!=(element_type* array) const { return impl_.get() != array; }
542
543 // Swap two scoped pointers.
544 void swap(scoped_ptr& p2) {
545 impl_.swap(p2.impl_);
546 }
547
548 // Release a pointer.
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000549 // The return value is the current pointer held by this object. If this object
550 // holds a nullptr, the return value is nullptr. After this operation, this
551 // object will hold a nullptr, and will not own the object any more.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000552 element_type* release() WARN_UNUSED_RESULT {
553 return impl_.release();
554 }
555
556 // Delete the currently held pointer and return a pointer
557 // to allow overwriting of the current pointer address.
558 element_type** accept() WARN_UNUSED_RESULT {
559 return impl_.accept();
560 }
561
562 // Return a pointer to the current pointer address.
563 element_type** use() WARN_UNUSED_RESULT {
564 return impl_.use();
565 }
566
567 private:
568 // Force element_type to be a complete type.
569 enum { type_must_be_complete = sizeof(element_type) };
570
571 // Actually hold the data.
572 rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
573
574 // Disable initialization from any type other than element_type*, by
575 // providing a constructor that matches such an initialization, but is
576 // private and has no definition. This is disabled because it is not safe to
577 // call delete[] on an array whose static type does not match its dynamic
578 // type.
579 template <typename U> explicit scoped_ptr(U* array);
580 explicit scoped_ptr(int disallow_construction_from_null);
581
582 // Disable reset() from any type other than element_type*, for the same
583 // reasons as the constructor above.
584 template <typename U> void reset(U* array);
585 void reset(int disallow_reset_from_null);
586
587 // Forbid comparison of scoped_ptr types. If U != T, it totally
588 // doesn't make sense, and if U == T, it still doesn't make sense
589 // because you should never have the same object owned by two different
590 // scoped_ptrs.
591 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
592 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
593};
594
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000595template <class T, class D>
596void swap(rtc::scoped_ptr<T, D>& p1, rtc::scoped_ptr<T, D>& p2) {
597 p1.swap(p2);
598}
599
Karl Wiberg94784372015-04-20 14:03:07 +0200600} // namespace rtc
601
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000602template <class T, class D>
603bool operator==(T* p1, const rtc::scoped_ptr<T, D>& p2) {
604 return p1 == p2.get();
605}
606
607template <class T, class D>
608bool operator!=(T* p1, const rtc::scoped_ptr<T, D>& p2) {
609 return p1 != p2.get();
610}
611
kwiberg@webrtc.org73ca1942015-01-29 09:12:47 +0000612// A function to convert T* into scoped_ptr<T>
613// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
614// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
615template <typename T>
616rtc::scoped_ptr<T> rtc_make_scoped_ptr(T* ptr) {
617 return rtc::scoped_ptr<T>(ptr);
618}
619
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000620#endif // #ifndef WEBRTC_BASE_SCOPED_PTR_H__