aboutsummaryrefslogtreecommitdiff
path: root/third_party/chromium/base/memory
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/chromium/base/memory')
-rw-r--r--third_party/chromium/base/memory/ref_counted.cc51
-rw-r--r--third_party/chromium/base/memory/ref_counted.h427
-rw-r--r--third_party/chromium/base/memory/ref_counted_unittest.cc451
-rw-r--r--third_party/chromium/base/memory/scoped_ptr.h594
-rw-r--r--third_party/chromium/base/memory/scoped_ptr_unittest.cc696
-rw-r--r--third_party/chromium/base/memory/weak_ptr.cc67
-rw-r--r--third_party/chromium/base/memory/weak_ptr.h336
-rw-r--r--third_party/chromium/base/memory/weak_ptr_unittest.cc153
8 files changed, 2775 insertions, 0 deletions
diff --git a/third_party/chromium/base/memory/ref_counted.cc b/third_party/chromium/base/memory/ref_counted.cc
new file mode 100644
index 0000000..42e777c
--- /dev/null
+++ b/third_party/chromium/base/memory/ref_counted.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+
+namespace base {
+
+namespace subtle {
+
+bool RefCountedThreadSafeBase::HasOneRef() const {
+ return ref_count_ == 1;
+}
+
+RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
+#ifndef NDEBUG
+ in_dtor_ = false;
+#endif
+}
+
+RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
+#ifndef NDEBUG
+ DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
+ "calling Release()";
+#endif
+}
+
+void RefCountedThreadSafeBase::AddRef() const {
+#ifndef NDEBUG
+ DCHECK(!in_dtor_);
+#endif
+ ++ref_count_;
+}
+
+bool RefCountedThreadSafeBase::Release() const {
+#ifndef NDEBUG
+ DCHECK(!in_dtor_);
+ DCHECK(ref_count_ != 0);
+#endif
+ if (--ref_count_ == 0) {
+#ifndef NDEBUG
+ in_dtor_ = true;
+#endif
+ return true;
+ }
+ return false;
+}
+
+} // namespace subtle
+
+} // namespace base
diff --git a/third_party/chromium/base/memory/ref_counted.h b/third_party/chromium/base/memory/ref_counted.h
new file mode 100644
index 0000000..23b9038
--- /dev/null
+++ b/third_party/chromium/base/memory/ref_counted.h
@@ -0,0 +1,427 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MEMORY_REF_COUNTED_H_
+#define BASE_MEMORY_REF_COUNTED_H_
+
+#include <atomic>
+#include <cassert>
+#include <iosfwd>
+
+#include "base/base_export.h"
+#include "base/build/build_config.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/move.h"
+
+namespace base {
+
+namespace subtle {
+
+class BASE_EXPORT RefCountedBase {
+ public:
+ bool HasOneRef() const { return ref_count_ == 1; }
+
+ protected:
+ RefCountedBase()
+ : ref_count_(0)
+ #ifndef NDEBUG
+ , in_dtor_(false)
+ #endif
+ {
+ }
+
+ ~RefCountedBase() {
+ #ifndef NDEBUG
+ DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
+ #endif
+ }
+
+
+ void AddRef() const {
+ #ifndef NDEBUG
+ DCHECK(!in_dtor_);
+ #endif
+ ++ref_count_;
+ }
+
+ // Returns true if the object should self-delete.
+ bool Release() const {
+ #ifndef NDEBUG
+ DCHECK(!in_dtor_);
+ #endif
+ if (--ref_count_ == 0) {
+ #ifndef NDEBUG
+ in_dtor_ = true;
+ #endif
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ mutable int ref_count_;
+#ifndef NDEBUG
+ mutable bool in_dtor_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
+};
+
+class BASE_EXPORT RefCountedThreadSafeBase {
+ public:
+ bool HasOneRef() const;
+
+ protected:
+ RefCountedThreadSafeBase();
+ ~RefCountedThreadSafeBase();
+
+ void AddRef() const;
+
+ // Returns true if the object should self-delete.
+ bool Release() const;
+
+ private:
+ mutable std::atomic<int32_t> ref_count_;
+#ifndef NDEBUG
+ mutable bool in_dtor_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
+};
+
+} // namespace subtle
+
+//
+// A base class for reference counted classes. Otherwise, known as a cheap
+// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
+// class from it like so:
+//
+// class MyFoo : public base::RefCounted<MyFoo> {
+// ...
+// private:
+// friend class base::RefCounted<MyFoo>;
+// ~MyFoo();
+// };
+//
+// You should always make your destructor private, to avoid any code deleting
+// the object accidently while there are references to it.
+template <class T>
+class RefCounted : public subtle::RefCountedBase {
+ public:
+ RefCounted() {}
+
+ void AddRef() const {
+ subtle::RefCountedBase::AddRef();
+ }
+
+ void Release() const {
+ if (subtle::RefCountedBase::Release()) {
+ delete static_cast<const T*>(this);
+ }
+ }
+
+ protected:
+ ~RefCounted() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
+};
+
+// Forward declaration.
+template <class T, typename Traits> class RefCountedThreadSafe;
+
+// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
+// count reaches 0. Overload to delete it on a different thread etc.
+template<typename T>
+struct DefaultRefCountedThreadSafeTraits {
+ static void Destruct(const T* x) {
+ // Delete through RefCountedThreadSafe to make child classes only need to be
+ // friend with RefCountedThreadSafe instead of this struct, which is an
+ // implementation detail.
+ RefCountedThreadSafe<T,
+ DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
+ }
+};
+
+//
+// A thread-safe variant of RefCounted<T>
+//
+// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
+// ...
+// };
+//
+// If you're using the default trait, then you should add compile time
+// asserts that no one else is deleting your object. i.e.
+// private:
+// friend class base::RefCountedThreadSafe<MyFoo>;
+// ~MyFoo();
+template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
+class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
+ public:
+ RefCountedThreadSafe() {}
+
+ void AddRef() const {
+ subtle::RefCountedThreadSafeBase::AddRef();
+ }
+
+ void Release() const {
+ if (subtle::RefCountedThreadSafeBase::Release()) {
+ Traits::Destruct(static_cast<const T*>(this));
+ }
+ }
+
+ protected:
+ ~RefCountedThreadSafe() {}
+
+ private:
+ friend struct DefaultRefCountedThreadSafeTraits<T>;
+ static void DeleteInternal(const T* x) { delete x; }
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
+};
+
+//
+// A thread-safe wrapper for some piece of data so we can place other
+// things in scoped_refptrs<>.
+//
+template<typename T>
+class RefCountedData
+ : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
+ public:
+ RefCountedData() : data() {}
+ RefCountedData(const T& in_value) : data(in_value) {}
+
+ T data;
+
+ private:
+ friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
+ ~RefCountedData() {}
+};
+
+} // namespace base
+
+//
+// A smart pointer class for reference counted objects. Use this class instead
+// of calling AddRef and Release manually on a reference counted object to
+// avoid common memory leaks caused by forgetting to Release an object
+// reference. Sample usage:
+//
+// class MyFoo : public RefCounted<MyFoo> {
+// ...
+// };
+//
+// void some_function() {
+// scoped_refptr<MyFoo> foo = new MyFoo();
+// foo->Method(param);
+// // |foo| is released when this function returns
+// }
+//
+// void some_other_function() {
+// scoped_refptr<MyFoo> foo = new MyFoo();
+// ...
+// foo = NULL; // explicitly releases |foo|
+// ...
+// if (foo)
+// foo->Method(param);
+// }
+//
+// The above examples show how scoped_refptr<T> acts like a pointer to T.
+// Given two scoped_refptr<T> classes, it is also possible to exchange
+// references between the two objects, like so:
+//
+// {
+// scoped_refptr<MyFoo> a = new MyFoo();
+// scoped_refptr<MyFoo> b;
+//
+// b.swap(a);
+// // now, |b| references the MyFoo object, and |a| references NULL.
+// }
+//
+// To make both |a| and |b| in the above example reference the same MyFoo
+// object, simply use the assignment operator:
+//
+// {
+// scoped_refptr<MyFoo> a = new MyFoo();
+// scoped_refptr<MyFoo> b;
+//
+// b = a;
+// // now, |a| and |b| each own a reference to the same MyFoo object.
+// }
+//
+template <class T>
+class scoped_refptr {
+ TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr)
+ public:
+ typedef T element_type;
+
+ scoped_refptr() : ptr_(NULL) {
+ }
+
+ scoped_refptr(T* p) : ptr_(p) {
+ if (ptr_)
+ AddRef(ptr_);
+ }
+
+ scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
+ if (ptr_)
+ AddRef(ptr_);
+ }
+
+ template <typename U>
+ scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
+ if (ptr_)
+ AddRef(ptr_);
+ }
+
+ template <typename U>
+ scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
+ r.ptr_ = nullptr;
+ }
+
+ ~scoped_refptr() {
+ if (ptr_)
+ Release(ptr_);
+ }
+
+ T* get() const { return ptr_; }
+
+ T& operator*() const {
+ assert(ptr_ != NULL);
+ return *ptr_;
+ }
+
+ T* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
+
+ scoped_refptr<T>& operator=(T* p) {
+ // AddRef first so that self assignment should work
+ if (p)
+ AddRef(p);
+ T* old_ptr = ptr_;
+ ptr_ = p;
+ if (old_ptr)
+ Release(old_ptr);
+ return *this;
+ }
+
+ scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
+ return *this = r.ptr_;
+ }
+
+ template <typename U>
+ scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
+ return *this = r.get();
+ }
+
+ scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
+ scoped_refptr<T>(r.Pass()).swap(*this);
+ return *this;
+ }
+
+ template <typename U>
+ scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
+ scoped_refptr<T>(r.Pass()).swap(*this);
+ return *this;
+ }
+
+ void swap(T** pp) {
+ T* p = ptr_;
+ ptr_ = *pp;
+ *pp = p;
+ }
+
+ void swap(scoped_refptr<T>& r) {
+ swap(&r.ptr_);
+ }
+
+ private:
+ template <typename U> friend class scoped_refptr;
+
+ // Allow scoped_refptr<T> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ //
+ // Note that this trick is only safe when the == and != operators
+ // are declared explicitly, as otherwise "refptr1 == refptr2"
+ // will compile but do the wrong thing (i.e., convert to Testable
+ // and then do the comparison).
+ typedef T* scoped_refptr::*Testable;
+
+ public:
+ operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; }
+
+ template <typename U>
+ bool operator==(const scoped_refptr<U>& rhs) const {
+ return ptr_ == rhs.get();
+ }
+
+ template <typename U>
+ bool operator!=(const scoped_refptr<U>& rhs) const {
+ return !operator==(rhs);
+ }
+
+ template <typename U>
+ bool operator<(const scoped_refptr<U>& rhs) const {
+ return ptr_ < rhs.get();
+ }
+
+ protected:
+ T* ptr_;
+
+ private:
+ // Non-inline helpers to allow:
+ // class Opaque;
+ // extern template class scoped_refptr<Opaque>;
+ // Otherwise the compiler will complain that Opaque is an incomplete type.
+ static void AddRef(T* ptr);
+ static void Release(T* ptr);
+};
+
+template <typename T>
+void scoped_refptr<T>::AddRef(T* ptr) {
+ ptr->AddRef();
+}
+
+template <typename T>
+void scoped_refptr<T>::Release(T* ptr) {
+ ptr->Release();
+}
+
+// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
+// having to retype all the template arguments
+template <typename T>
+scoped_refptr<T> make_scoped_refptr(T* t) {
+ return scoped_refptr<T>(t);
+}
+
+// Temporary operator overloads to facilitate the transition. See
+// https://crbug.com/110610.
+template <typename T, typename U>
+bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
+ return lhs.get() == rhs;
+}
+
+template <typename T, typename U>
+bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
+ return lhs == rhs.get();
+}
+
+template <typename T, typename U>
+bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
+ return !operator==(lhs, rhs);
+}
+
+template <typename T, typename U>
+bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
+ return !operator==(lhs, rhs);
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
+ return out << p.get();
+}
+
+#endif // BASE_MEMORY_REF_COUNTED_H_
diff --git a/third_party/chromium/base/memory/ref_counted_unittest.cc b/third_party/chromium/base/memory/ref_counted_unittest.cc
new file mode 100644
index 0000000..9eda813
--- /dev/null
+++ b/third_party/chromium/base/memory/ref_counted_unittest.cc
@@ -0,0 +1,451 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+
+#include <gtest/gtest.h>
+
+namespace {
+
+class SelfAssign : public base::RefCounted<SelfAssign> {
+ protected:
+ virtual ~SelfAssign() {}
+
+ private:
+ friend class base::RefCounted<SelfAssign>;
+};
+
+class Derived : public SelfAssign {
+ protected:
+ ~Derived() override {}
+
+ private:
+ friend class base::RefCounted<Derived>;
+};
+
+class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
+ public:
+ CheckDerivedMemberAccess() {
+ // This shouldn't compile if we don't have access to the member variable.
+ SelfAssign** pptr = &ptr_;
+ EXPECT_EQ(*pptr, ptr_);
+ }
+};
+
+class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
+ public:
+ ScopedRefPtrToSelf() : self_ptr_(this) {}
+
+ static bool was_destroyed() { return was_destroyed_; }
+
+ static void reset_was_destroyed() { was_destroyed_ = false; }
+
+ scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
+
+ private:
+ friend class base::RefCounted<ScopedRefPtrToSelf>;
+ ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
+
+ static bool was_destroyed_;
+};
+
+bool ScopedRefPtrToSelf::was_destroyed_ = false;
+
+class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
+ public:
+ ScopedRefPtrCountBase() { ++constructor_count_; }
+
+ static int constructor_count() { return constructor_count_; }
+
+ static int destructor_count() { return destructor_count_; }
+
+ static void reset_count() {
+ constructor_count_ = 0;
+ destructor_count_ = 0;
+ }
+
+ protected:
+ virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
+
+ private:
+ friend class base::RefCounted<ScopedRefPtrCountBase>;
+
+ static int constructor_count_;
+ static int destructor_count_;
+};
+
+int ScopedRefPtrCountBase::constructor_count_ = 0;
+int ScopedRefPtrCountBase::destructor_count_ = 0;
+
+class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
+ public:
+ ScopedRefPtrCountDerived() { ++constructor_count_; }
+
+ static int constructor_count() { return constructor_count_; }
+
+ static int destructor_count() { return destructor_count_; }
+
+ static void reset_count() {
+ constructor_count_ = 0;
+ destructor_count_ = 0;
+ }
+
+ protected:
+ ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
+
+ private:
+ friend class base::RefCounted<ScopedRefPtrCountDerived>;
+
+ static int constructor_count_;
+ static int destructor_count_;
+};
+
+int ScopedRefPtrCountDerived::constructor_count_ = 0;
+int ScopedRefPtrCountDerived::destructor_count_ = 0;
+
+} // end namespace
+
+TEST(RefCountedUnitTest, TestSelfAssignment) {
+ SelfAssign* p = new SelfAssign;
+ scoped_refptr<SelfAssign> var(p);
+ var = var;
+ EXPECT_EQ(var.get(), p);
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
+ CheckDerivedMemberAccess check;
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
+ ScopedRefPtrToSelf::reset_was_destroyed();
+
+ ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
+ EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
+ check->self_ptr_ = nullptr;
+ EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
+ ScopedRefPtrToSelf::reset_was_destroyed();
+
+ ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
+ EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
+ // Releasing |check->self_ptr_| will delete |check|.
+ // The move assignment operator must assign |check->self_ptr_| first then
+ // release |check->self_ptr_|.
+ check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
+ EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
+}
+
+TEST(RefCountedUnitTest, BooleanTesting) {
+ scoped_refptr<SelfAssign> p;
+ EXPECT_FALSE(p);
+ p = new SelfAssign;
+ EXPECT_TRUE(p);
+}
+
+TEST(RefCountedUnitTest, Equality) {
+ scoped_refptr<SelfAssign> p1(new SelfAssign);
+ scoped_refptr<SelfAssign> p2(new SelfAssign);
+
+ EXPECT_EQ(p1, p1);
+ EXPECT_EQ(p2, p2);
+
+ EXPECT_NE(p1, p2);
+ EXPECT_NE(p2, p1);
+}
+
+TEST(RefCountedUnitTest, ConvertibleEquality) {
+ scoped_refptr<Derived> p1(new Derived);
+ scoped_refptr<SelfAssign> p2;
+
+ EXPECT_NE(p1, p2);
+ EXPECT_NE(p2, p1);
+
+ p2 = p1;
+
+ EXPECT_EQ(p1, p2);
+ EXPECT_EQ(p2, p1);
+}
+
+TEST(RefCountedUnitTest, SelfMoveAssignment) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p = p.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p.get());
+
+ // p goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment1) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2;
+
+ p2 = p1.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment2) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1;
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p2 = p1.Pass();
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(raw2, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDerived) {
+ ScopedRefPtrCountBase::reset_count();
+ ScopedRefPtrCountDerived::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ {
+ ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
+ scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ p1 = p2.Pass();
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+ EXPECT_EQ(raw2, p1.get());
+ EXPECT_EQ(nullptr, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructor) {
+ ScopedRefPtrCountBase::reset_count();
+
+ {
+ ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+ scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructorDerived) {
+ ScopedRefPtrCountBase::reset_count();
+ ScopedRefPtrCountDerived::reset_count();
+
+ {
+ ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
+ scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+ {
+ scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+ EXPECT_EQ(nullptr, p1.get());
+ EXPECT_EQ(raw1, p2.get());
+
+ // p2 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+
+ // p1 goes out of scope.
+ }
+ EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+ EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
diff --git a/third_party/chromium/base/memory/scoped_ptr.h b/third_party/chromium/base/memory/scoped_ptr.h
new file mode 100644
index 0000000..2aa1b32
--- /dev/null
+++ b/third_party/chromium/base/memory/scoped_ptr.h
@@ -0,0 +1,594 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Scopers help you manage ownership of a pointer, helping you easily manage a
+// pointer within a scope, and automatically destroying the pointer at the end
+// of a scope. There are two main classes you will use, which correspond to the
+// operators new/delete and new[]/delete[].
+//
+// Example usage (scoped_ptr<T>):
+// {
+// scoped_ptr<Foo> foo(new Foo("wee"));
+// } // foo goes out of scope, releasing the pointer with it.
+//
+// {
+// scoped_ptr<Foo> foo; // No pointer managed.
+// foo.reset(new Foo("wee")); // Now a pointer is managed.
+// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
+// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
+// foo->Method(); // Foo::Method() called.
+// foo.get()->Method(); // Foo::Method() called.
+// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
+// // manages a pointer.
+// foo.reset(new Foo("wee4")); // foo manages a pointer again.
+// foo.reset(); // Foo("wee4") destroyed, foo no longer
+// // manages a pointer.
+// } // foo wasn't managing a pointer, so nothing was destroyed.
+//
+// Example usage (scoped_ptr<T[]>):
+// {
+// scoped_ptr<Foo[]> foo(new Foo[100]);
+// foo.get()->Method(); // Foo::Method on the 0th element.
+// foo[10].Method(); // Foo::Method on the 10th element.
+// }
+//
+// These scopers also implement part of the functionality of C++11 unique_ptr
+// in that they are "movable but not copyable." You can use the scopers in
+// the parameter and return types of functions to signify ownership transfer
+// in to and out of a function. When calling a function that has a scoper
+// as the argument type, it must be called with the result of an analogous
+// scoper's Pass() function or another function that generates a temporary;
+// passing by copy will NOT work. Here is an example using scoped_ptr:
+//
+// void TakesOwnership(scoped_ptr<Foo> arg) {
+// // Do something with arg
+// }
+// scoped_ptr<Foo> CreateFoo() {
+// // No need for calling Pass() because we are constructing a temporary
+// // for the return value.
+// return scoped_ptr<Foo>(new Foo("new"));
+// }
+// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
+// return arg.Pass();
+// }
+//
+// {
+// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
+// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
+// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
+// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
+// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr.
+// }
+//
+// Notice that if you do not call Pass() when returning from PassThru(), or
+// when invoking TakesOwnership(), the code will not compile because scopers
+// are not copyable; they only implement move semantics which require calling
+// the Pass() function to signify a destructive transfer of state. CreateFoo()
+// is different though because we are constructing a temporary on the return
+// line and thus can avoid needing to call Pass().
+//
+// Pass() properly handles upcast in initialization, i.e. you can use a
+// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
+//
+// scoped_ptr<Foo> foo(new Foo());
+// scoped_ptr<FooParent> parent(foo.Pass());
+
+#ifndef BASE_MEMORY_SCOPED_PTR_H_
+#define BASE_MEMORY_SCOPED_PTR_H_
+
+// This is an implementation designed to match the anticipated future TR2
+// implementation of the scoped_ptr class.
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <algorithm> // For std::swap().
+#include <iosfwd>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/move.h"
+#include "base/template_util.h"
+
+namespace base {
+
+namespace subtle {
+class RefCountedBase;
+class RefCountedThreadSafeBase;
+} // namespace subtle
+
+// Function object which deletes its parameter, which must be a pointer.
+// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
+// invokes 'delete'. The default deleter for scoped_ptr<T>.
+template <class T>
+struct DefaultDeleter {
+ DefaultDeleter() {}
+ template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
+ // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
+ // if U* is implicitly convertible to T* and U is not an array type.
+ //
+ // Correct implementation should use SFINAE to disable this
+ // constructor. However, since there are no other 1-argument constructors,
+ // using a COMPILE_ASSERT() based on is_convertible<> and requiring
+ // complete types is simpler and will cause compile failures for equivalent
+ // misuses.
+ //
+ // Note, the is_convertible<U*, T*> check also ensures that U is not an
+ // array. T is guaranteed to be a non-array, so any U* where U is an array
+ // cannot convert to T*.
+ enum { T_must_be_complete = sizeof(T) };
+ enum { U_must_be_complete = sizeof(U) };
+ COMPILE_ASSERT((std::is_convertible<U*, T*>::value),
+ U_ptr_must_implicitly_convert_to_T_ptr);
+ }
+ inline void operator()(T* ptr) const {
+ enum { type_must_be_complete = sizeof(T) };
+ delete ptr;
+ }
+};
+
+// Specialization of DefaultDeleter for array types.
+template <class T>
+struct DefaultDeleter<T[]> {
+ inline void operator()(T* ptr) const {
+ enum { type_must_be_complete = sizeof(T) };
+ delete[] ptr;
+ }
+
+ private:
+ // Disable this operator for any U != T because it is undefined to execute
+ // an array delete when the static type of the array mismatches the dynamic
+ // type.
+ //
+ // References:
+ // C++98 [expr.delete]p3
+ // http://cplusplus.github.com/LWG/lwg-defects.html#938
+ template <typename U> void operator()(U* array) const;
+};
+
+template <class T, int n>
+struct DefaultDeleter<T[n]> {
+ // Never allow someone to declare something like scoped_ptr<int[10]>.
+ COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
+};
+
+// Function object which invokes 'free' on its parameter, which must be
+// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
+//
+// scoped_ptr<int, base::FreeDeleter> foo_ptr(
+// static_cast<int*>(malloc(sizeof(int))));
+struct FreeDeleter {
+ inline void operator()(void* ptr) const {
+ free(ptr);
+ }
+};
+
+namespace internal {
+
+template <typename T> struct IsNotRefCounted {
+ enum {
+ value = !std::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
+ !std::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
+ value
+ };
+};
+
+template <typename T>
+struct ShouldAbortOnSelfReset {
+ template <typename U>
+ static NoType Test(const typename U::AllowSelfReset*);
+
+ template <typename U>
+ static YesType Test(...);
+
+ static const bool value = sizeof(Test<T>(0)) == sizeof(YesType);
+};
+
+// Minimal implementation of the core logic of scoped_ptr, suitable for
+// reuse in both scoped_ptr and its specializations.
+template <class T, class D>
+class scoped_ptr_impl {
+ public:
+ explicit scoped_ptr_impl(T* p) : data_(p) {}
+
+ // Initializer for deleters that have data parameters.
+ scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
+
+ // Templated constructor that destructively takes the value from another
+ // scoped_ptr_impl.
+ template <typename U, typename V>
+ scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
+ : data_(other->release(), other->get_deleter()) {
+ // We do not support move-only deleters. We could modify our move
+ // emulation to have base::subtle::move() and base::subtle::forward()
+ // functions that are imperfect emulations of their C++11 equivalents,
+ // but until there's a requirement, just assume deleters are copyable.
+ }
+
+ template <typename U, typename V>
+ void TakeState(scoped_ptr_impl<U, V>* other) {
+ // See comment in templated constructor above regarding lack of support
+ // for move-only deleters.
+ reset(other->release());
+ get_deleter() = other->get_deleter();
+ }
+
+ ~scoped_ptr_impl() {
+ if (data_.ptr != nullptr) {
+ // Not using get_deleter() saves one function call in non-optimized
+ // builds.
+ static_cast<D&>(data_)(data_.ptr);
+ }
+ }
+
+ void reset(T* p) {
+ // This is a self-reset, which is no longer allowed for default deleters:
+ // https://crbug.com/162971
+ assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
+
+ // Note that running data_.ptr = p can lead to undefined behavior if
+ // get_deleter()(get()) deletes this. In order to prevent this, reset()
+ // should update the stored pointer before deleting its old value.
+ //
+ // However, changing reset() to use that behavior may cause current code to
+ // break in unexpected ways. If the destruction of the owned object
+ // dereferences the scoped_ptr when it is destroyed by a call to reset(),
+ // then it will incorrectly dispatch calls to |p| rather than the original
+ // value of |data_.ptr|.
+ //
+ // During the transition period, set the stored pointer to nullptr while
+ // deleting the object. Eventually, this safety check will be removed to
+ // prevent the scenario initially described from occuring and
+ // http://crbug.com/176091 can be closed.
+ T* old = data_.ptr;
+ data_.ptr = nullptr;
+ if (old != nullptr)
+ static_cast<D&>(data_)(old);
+ data_.ptr = p;
+ }
+
+ T* get() const { return data_.ptr; }
+
+ D& get_deleter() { return data_; }
+ const D& get_deleter() const { return data_; }
+
+ void swap(scoped_ptr_impl& p2) {
+ // Standard swap idiom: 'using std::swap' ensures that std::swap is
+ // present in the overload set, but we call swap unqualified so that
+ // any more-specific overloads can be used, if available.
+ using std::swap;
+ swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
+ swap(data_.ptr, p2.data_.ptr);
+ }
+
+ T* release() {
+ T* old_ptr = data_.ptr;
+ data_.ptr = nullptr;
+ return old_ptr;
+ }
+
+ private:
+ // Needed to allow type-converting constructor.
+ template <typename U, typename V> friend class scoped_ptr_impl;
+
+ // Use the empty base class optimization to allow us to have a D
+ // member, while avoiding any space overhead for it when D is an
+ // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
+ // discussion of this technique.
+ struct Data : public D {
+ explicit Data(T* ptr_in) : ptr(ptr_in) {}
+ Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
+ T* ptr;
+ };
+
+ Data data_;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
+};
+
+} // namespace internal
+
+} // namespace base
+
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
+// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
+// dereference it, you get the thread safety guarantees of T.
+//
+// The size of scoped_ptr is small. On most compilers, when using the
+// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
+// increase the size proportional to whatever state they need to have. See
+// comments inside scoped_ptr_impl<> for details.
+//
+// Current implementation targets having a strict subset of C++11's
+// unique_ptr<> features. Known deficiencies include not supporting move-only
+// deleteres, function pointers as deleters, and deleters with reference
+// types.
+template <class T, class D = base::DefaultDeleter<T> >
+class scoped_ptr {
+ MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
+
+ COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
+ T_is_refcounted_type_and_needs_scoped_refptr);
+
+ public:
+ // The element and deleter types.
+ typedef T element_type;
+ typedef D deleter_type;
+
+ // Constructor. Defaults to initializing with nullptr.
+ scoped_ptr() : impl_(nullptr) {}
+
+ // Constructor. Takes ownership of p.
+ explicit scoped_ptr(element_type* p) : impl_(p) {}
+
+ // Constructor. Allows initialization of a stateful deleter.
+ scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
+
+ // Constructor. Allows construction from a nullptr.
+ scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
+
+ // Constructor. Allows construction from a scoped_ptr rvalue for a
+ // convertible type and deleter.
+ //
+ // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
+ // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
+ // has different post-conditions if D is a reference type. Since this
+ // implementation does not support deleters with reference type,
+ // we do not need a separate move constructor allowing us to avoid one
+ // use of SFINAE. You only need to care about this if you modify the
+ // implementation of scoped_ptr.
+ template <typename U, typename V>
+ scoped_ptr(scoped_ptr<U, V>&& other)
+ : impl_(&other.impl_) {
+ COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array);
+ }
+
+ // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
+ // type and deleter.
+ //
+ // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
+ // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
+ // form has different requirements on for move-only Deleters. Since this
+ // implementation does not support move-only Deleters, we do not need a
+ // separate move assignment operator allowing us to avoid one use of SFINAE.
+ // You only need to care about this if you modify the implementation of
+ // scoped_ptr.
+ template <typename U, typename V>
+ scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) {
+ COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array);
+ impl_.TakeState(&rhs.impl_);
+ return *this;
+ }
+
+ // operator=. Allows assignment from a nullptr. Deletes the currently owned
+ // object, if any.
+ scoped_ptr& operator=(decltype(nullptr)) {
+ reset();
+ return *this;
+ }
+
+ // Reset. Deletes the currently owned object, if any.
+ // Then takes ownership of a new object, if given.
+ void reset(element_type* p = nullptr) { impl_.reset(p); }
+
+ // Accessors to get the owned object.
+ // operator* and operator-> will assert() if there is no current object.
+ element_type& operator*() const {
+ assert(impl_.get() != nullptr);
+ return *impl_.get();
+ }
+ element_type* operator->() const {
+ assert(impl_.get() != nullptr);
+ return impl_.get();
+ }
+ element_type* get() const { return impl_.get(); }
+
+ // Access to the deleter.
+ deleter_type& get_deleter() { return impl_.get_deleter(); }
+ const deleter_type& get_deleter() const { return impl_.get_deleter(); }
+
+ // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ //
+ // Note that this trick is only safe when the == and != operators
+ // are declared explicitly, as otherwise "scoped_ptr1 ==
+ // scoped_ptr2" will compile but do the wrong thing (i.e., convert
+ // to Testable and then do the comparison).
+ private:
+ typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
+ scoped_ptr::*Testable;
+
+ public:
+ operator Testable() const {
+ return impl_.get() ? &scoped_ptr::impl_ : nullptr;
+ }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(const element_type* p) const { return impl_.get() == p; }
+ bool operator!=(const element_type* p) const { return impl_.get() != p; }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ impl_.swap(p2.impl_);
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object. If this object
+ // holds a nullptr, the return value is nullptr. After this operation, this
+ // object will hold a nullptr, and will not own the object any more.
+ element_type* release() WARN_UNUSED_RESULT {
+ return impl_.release();
+ }
+
+ private:
+ // Needed to reach into |impl_| in the constructor.
+ template <typename U, typename V> friend class scoped_ptr;
+ base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
+
+ // Forbidden for API compatibility with std::unique_ptr.
+ explicit scoped_ptr(int disallow_construction_from_null);
+
+ // Forbid comparison of scoped_ptr types. If U != T, it totally
+ // doesn't make sense, and if U == T, it still doesn't make sense
+ // because you should never have the same object owned by two different
+ // scoped_ptrs.
+ template <class U> bool operator==(scoped_ptr<U> const& p2) const;
+ template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
+};
+
+template <class T, class D>
+class scoped_ptr<T[], D> {
+ MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
+
+ public:
+ // The element and deleter types.
+ typedef T element_type;
+ typedef D deleter_type;
+
+ // Constructor. Defaults to initializing with nullptr.
+ scoped_ptr() : impl_(nullptr) {}
+
+ // Constructor. Stores the given array. Note that the argument's type
+ // must exactly match T*. In particular:
+ // - it cannot be a pointer to a type derived from T, because it is
+ // inherently unsafe in the general case to access an array through a
+ // pointer whose dynamic type does not match its static type (eg., if
+ // T and the derived types had different sizes access would be
+ // incorrectly calculated). Deletion is also always undefined
+ // (C++98 [expr.delete]p3). If you're doing this, fix your code.
+ // - it cannot be const-qualified differently from T per unique_ptr spec
+ // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
+ // to work around this may use implicit_cast<const T*>().
+ // However, because of the first bullet in this comment, users MUST
+ // NOT use implicit_cast<Base*>() to upcast the static type of the array.
+ explicit scoped_ptr(element_type* array) : impl_(array) {}
+
+ // Constructor. Allows construction from a nullptr.
+ scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
+
+ // Constructor. Allows construction from a scoped_ptr rvalue.
+ scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
+
+ // operator=. Allows assignment from a scoped_ptr rvalue.
+ scoped_ptr& operator=(scoped_ptr&& rhs) {
+ impl_.TakeState(&rhs.impl_);
+ return *this;
+ }
+
+ // operator=. Allows assignment from a nullptr. Deletes the currently owned
+ // array, if any.
+ scoped_ptr& operator=(decltype(nullptr)) {
+ reset();
+ return *this;
+ }
+
+ // Reset. Deletes the currently owned array, if any.
+ // Then takes ownership of a new object, if given.
+ void reset(element_type* array = nullptr) { impl_.reset(array); }
+
+ // Accessors to get the owned array.
+ element_type& operator[](size_t i) const {
+ assert(impl_.get() != nullptr);
+ return impl_.get()[i];
+ }
+ element_type* get() const { return impl_.get(); }
+
+ // Access to the deleter.
+ deleter_type& get_deleter() { return impl_.get_deleter(); }
+ const deleter_type& get_deleter() const { return impl_.get_deleter(); }
+
+ // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ private:
+ typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
+ scoped_ptr::*Testable;
+
+ public:
+ operator Testable() const {
+ return impl_.get() ? &scoped_ptr::impl_ : nullptr;
+ }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(element_type* array) const { return impl_.get() == array; }
+ bool operator!=(element_type* array) const { return impl_.get() != array; }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ impl_.swap(p2.impl_);
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object. If this object
+ // holds a nullptr, the return value is nullptr. After this operation, this
+ // object will hold a nullptr, and will not own the object any more.
+ element_type* release() WARN_UNUSED_RESULT {
+ return impl_.release();
+ }
+
+ private:
+ // Force element_type to be a complete type.
+ enum { type_must_be_complete = sizeof(element_type) };
+
+ // Actually hold the data.
+ base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
+
+ // Disable initialization from any type other than element_type*, by
+ // providing a constructor that matches such an initialization, but is
+ // private and has no definition. This is disabled because it is not safe to
+ // call delete[] on an array whose static type does not match its dynamic
+ // type.
+ template <typename U> explicit scoped_ptr(U* array);
+ explicit scoped_ptr(int disallow_construction_from_null);
+
+ // Disable reset() from any type other than element_type*, for the same
+ // reasons as the constructor above.
+ template <typename U> void reset(U* array);
+ void reset(int disallow_reset_from_null);
+
+ // Forbid comparison of scoped_ptr types. If U != T, it totally
+ // doesn't make sense, and if U == T, it still doesn't make sense
+ // because you should never have the same object owned by two different
+ // scoped_ptrs.
+ template <class U> bool operator==(scoped_ptr<U> const& p2) const;
+ template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
+};
+
+// Free functions
+template <class T, class D>
+void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
+ p1.swap(p2);
+}
+
+template <class T, class D>
+bool operator==(T* p1, const scoped_ptr<T, D>& p2) {
+ return p1 == p2.get();
+}
+
+template <class T, class D>
+bool operator!=(T* p1, const scoped_ptr<T, D>& p2) {
+ return p1 != p2.get();
+}
+
+// A function to convert T* into scoped_ptr<T>
+// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+scoped_ptr<T> make_scoped_ptr(T* ptr) {
+ return scoped_ptr<T>(ptr);
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
+ return out << p.get();
+}
+
+#endif // BASE_MEMORY_SCOPED_PTR_H_
diff --git a/third_party/chromium/base/memory/scoped_ptr_unittest.cc b/third_party/chromium/base/memory/scoped_ptr_unittest.cc
new file mode 100644
index 0000000..d4ff410
--- /dev/null
+++ b/third_party/chromium/base/memory/scoped_ptr_unittest.cc
@@ -0,0 +1,696 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+
+#include <sstream>
+
+#include <gtest/gtest.h>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+
+namespace {
+
+// Used to test depth subtyping.
+class ConDecLoggerParent {
+ public:
+ virtual ~ConDecLoggerParent() {}
+
+ virtual void SetPtr(int* ptr) = 0;
+
+ virtual int SomeMeth(int x) const = 0;
+};
+
+class ConDecLogger : public ConDecLoggerParent {
+ public:
+ ConDecLogger() : ptr_(NULL) { }
+ explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
+ ~ConDecLogger() override { --*ptr_; }
+
+ void SetPtr(int* ptr) override {
+ ptr_ = ptr;
+ ++*ptr_;
+ }
+
+ int SomeMeth(int x) const override { return x; }
+
+ private:
+ int* ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
+};
+
+struct CountingDeleter {
+ explicit CountingDeleter(int* count) : count_(count) {}
+ inline void operator()(double* ptr) const {
+ (*count_)++;
+ }
+ int* count_;
+};
+
+// Used to test assignment of convertible deleters.
+struct CountingDeleterChild : public CountingDeleter {
+ explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
+};
+
+class OverloadedNewAndDelete {
+ public:
+ void* operator new(size_t size) {
+ g_new_count++;
+ return malloc(size);
+ }
+
+ void operator delete(void* ptr) {
+ g_delete_count++;
+ free(ptr);
+ }
+
+ static void ResetCounters() {
+ g_new_count = 0;
+ g_delete_count = 0;
+ }
+
+ static int new_count() { return g_new_count; }
+ static int delete_count() { return g_delete_count; }
+
+ private:
+ static int g_new_count;
+ static int g_delete_count;
+};
+
+int OverloadedNewAndDelete::g_new_count = 0;
+int OverloadedNewAndDelete::g_delete_count = 0;
+
+scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
+ return logger.Pass();
+}
+
+void GrabAndDrop(scoped_ptr<ConDecLogger> logger) {
+}
+
+// Do not delete this function! It's existence is to test that you can
+// return a temporarily constructed version of the scoper.
+scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
+ return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
+}
+
+} // namespace
+
+TEST(ScopedPtrTest, ScopedPtr) {
+ int constructed = 0;
+
+ // Ensure size of scoped_ptr<> doesn't increase unexpectedly.
+ COMPILE_ASSERT(sizeof(int*) >= sizeof(scoped_ptr<int>),
+ scoped_ptr_larger_than_raw_ptr);
+
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ EXPECT_EQ(10, scoper->SomeMeth(10));
+ EXPECT_EQ(10, scoper.get()->SomeMeth(10));
+ EXPECT_EQ(10, (*scoper).SomeMeth(10));
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test reset() and release()
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoper.reset(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoper.reset();
+ EXPECT_EQ(0, constructed);
+ EXPECT_FALSE(scoper.get());
+
+ scoper.reset(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ ConDecLogger* take = scoper.release();
+ EXPECT_EQ(1, constructed);
+ EXPECT_FALSE(scoper.get());
+ delete take;
+ EXPECT_EQ(0, constructed);
+
+ scoper.reset(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test swap(), == and !=
+ {
+ scoped_ptr<ConDecLogger> scoper1;
+ scoped_ptr<ConDecLogger> scoper2;
+ EXPECT_TRUE(scoper1 == scoper2.get());
+ EXPECT_FALSE(scoper1 != scoper2.get());
+
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoper1.reset(logger);
+ EXPECT_EQ(logger, scoper1.get());
+ EXPECT_FALSE(scoper2.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+
+ scoper2.swap(scoper1);
+ EXPECT_EQ(logger, scoper2.get());
+ EXPECT_FALSE(scoper1.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+ }
+ EXPECT_EQ(0, constructed);
+}
+
+TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) {
+ int constructed = 0;
+
+ // Test construction from a scoped_ptr to a derived class.
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoped_ptr<ConDecLoggerParent> scoper_parent(scoper.Pass());
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper_parent.get());
+ EXPECT_FALSE(scoper.get());
+
+ EXPECT_EQ(10, scoper_parent->SomeMeth(10));
+ EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10));
+ EXPECT_EQ(10, (*scoper_parent).SomeMeth(10));
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test assignment from a scoped_ptr to a derived class.
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoped_ptr<ConDecLoggerParent> scoper_parent;
+ scoper_parent = scoper.Pass();
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper_parent.get());
+ EXPECT_FALSE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test construction of a scoped_ptr with an additional const annotation.
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoped_ptr<const ConDecLogger> scoper_const(scoper.Pass());
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper_const.get());
+ EXPECT_FALSE(scoper.get());
+
+ EXPECT_EQ(10, scoper_const->SomeMeth(10));
+ EXPECT_EQ(10, scoper_const.get()->SomeMeth(10));
+ EXPECT_EQ(10, (*scoper_const).SomeMeth(10));
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test assignment to a scoped_ptr with an additional const annotation.
+ {
+ scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper.get());
+
+ scoped_ptr<const ConDecLogger> scoper_const;
+ scoper_const = scoper.Pass();
+ EXPECT_EQ(1, constructed);
+ EXPECT_TRUE(scoper_const.get());
+ EXPECT_FALSE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test assignment to a scoped_ptr deleter of parent type.
+ {
+ // Custom deleters never touch these value.
+ double dummy_value, dummy_value2;
+ int deletes = 0;
+ int alternate_deletes = 0;
+ scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
+ CountingDeleter(&deletes));
+ scoped_ptr<double, CountingDeleterChild> scoper_child(
+ &dummy_value2, CountingDeleterChild(&alternate_deletes));
+
+ EXPECT_TRUE(scoper);
+ EXPECT_TRUE(scoper_child);
+ EXPECT_EQ(0, deletes);
+ EXPECT_EQ(0, alternate_deletes);
+
+ // Test this compiles and correctly overwrites the deleter state.
+ scoper = scoper_child.Pass();
+ EXPECT_TRUE(scoper);
+ EXPECT_FALSE(scoper_child);
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(0, alternate_deletes);
+
+ scoper.reset();
+ EXPECT_FALSE(scoper);
+ EXPECT_FALSE(scoper_child);
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(1, alternate_deletes);
+
+ scoper_child.reset(&dummy_value);
+ EXPECT_TRUE(scoper_child);
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(1, alternate_deletes);
+ scoped_ptr<double, CountingDeleter> scoper_construct(scoper_child.Pass());
+ EXPECT_TRUE(scoper_construct);
+ EXPECT_FALSE(scoper_child);
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(1, alternate_deletes);
+
+ scoper_construct.reset();
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(2, alternate_deletes);
+ }
+}
+
+TEST(ScopedPtrTest, ScopedPtrWithArray) {
+ static const int kNumLoggers = 12;
+
+ int constructed = 0;
+
+ {
+ scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]);
+ EXPECT_TRUE(scoper);
+ EXPECT_EQ(&scoper[0], scoper.get());
+ for (int i = 0; i < kNumLoggers; ++i) {
+ scoper[i].SetPtr(&constructed);
+ }
+ EXPECT_EQ(12, constructed);
+
+ EXPECT_EQ(10, scoper.get()->SomeMeth(10));
+ EXPECT_EQ(10, scoper[2].SomeMeth(10));
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test reset() and release()
+ {
+ scoped_ptr<ConDecLogger[]> scoper;
+ EXPECT_FALSE(scoper.get());
+ EXPECT_FALSE(scoper.release());
+ EXPECT_FALSE(scoper.get());
+ scoper.reset();
+ EXPECT_FALSE(scoper.get());
+
+ scoper.reset(new ConDecLogger[kNumLoggers]);
+ for (int i = 0; i < kNumLoggers; ++i) {
+ scoper[i].SetPtr(&constructed);
+ }
+ EXPECT_EQ(12, constructed);
+ scoper.reset();
+ EXPECT_EQ(0, constructed);
+
+ scoper.reset(new ConDecLogger[kNumLoggers]);
+ for (int i = 0; i < kNumLoggers; ++i) {
+ scoper[i].SetPtr(&constructed);
+ }
+ EXPECT_EQ(12, constructed);
+ ConDecLogger* ptr = scoper.release();
+ EXPECT_EQ(12, constructed);
+ delete[] ptr;
+ EXPECT_EQ(0, constructed);
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test swap(), ==, !=, and type-safe Boolean.
+ {
+ scoped_ptr<ConDecLogger[]> scoper1;
+ scoped_ptr<ConDecLogger[]> scoper2;
+ EXPECT_TRUE(scoper1 == scoper2.get());
+ EXPECT_FALSE(scoper1 != scoper2.get());
+
+ ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
+ for (int i = 0; i < kNumLoggers; ++i) {
+ loggers[i].SetPtr(&constructed);
+ }
+ scoper1.reset(loggers);
+ EXPECT_TRUE(scoper1);
+ EXPECT_EQ(loggers, scoper1.get());
+ EXPECT_FALSE(scoper2);
+ EXPECT_FALSE(scoper2.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+
+ scoper2.swap(scoper1);
+ EXPECT_EQ(loggers, scoper2.get());
+ EXPECT_FALSE(scoper1.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ {
+ ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
+ scoped_ptr<ConDecLogger[]> scoper(loggers);
+ EXPECT_TRUE(scoper);
+ for (int i = 0; i < kNumLoggers; ++i) {
+ scoper[i].SetPtr(&constructed);
+ }
+ EXPECT_EQ(kNumLoggers, constructed);
+
+ // Test Pass() with constructor;
+ scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass());
+ EXPECT_EQ(kNumLoggers, constructed);
+
+ // Test Pass() with assignment;
+ scoped_ptr<ConDecLogger[]> scoper3;
+ scoper3 = scoper2.Pass();
+ EXPECT_EQ(kNumLoggers, constructed);
+ EXPECT_FALSE(scoper);
+ EXPECT_FALSE(scoper2);
+ EXPECT_TRUE(scoper3);
+ }
+ EXPECT_EQ(0, constructed);
+}
+
+TEST(ScopedPtrTest, PassBehavior) {
+ int constructed = 0;
+ {
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoped_ptr<ConDecLogger> scoper(logger);
+ EXPECT_EQ(1, constructed);
+
+ // Test Pass() with constructor;
+ scoped_ptr<ConDecLogger> scoper2(scoper.Pass());
+ EXPECT_EQ(1, constructed);
+
+ // Test Pass() with assignment;
+ scoped_ptr<ConDecLogger> scoper3;
+ scoper3 = scoper2.Pass();
+ EXPECT_EQ(1, constructed);
+ EXPECT_FALSE(scoper.get());
+ EXPECT_FALSE(scoper2.get());
+ EXPECT_TRUE(scoper3.get());
+ }
+
+ // Test uncaught Pass() does not have side effects.
+ {
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoped_ptr<ConDecLogger> scoper(logger);
+ EXPECT_EQ(1, constructed);
+
+ // Should auto-destruct logger by end of scope.
+ scoped_ptr<ConDecLogger>&& rvalue = scoper.Pass();
+ // The Pass() function mimics std::move(), which does not have side-effects.
+ EXPECT_TRUE(scoper.get());
+ EXPECT_TRUE(rvalue);
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test that passing to function which does nothing does not leak.
+ {
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoped_ptr<ConDecLogger> scoper(logger);
+ EXPECT_EQ(1, constructed);
+
+ // Should auto-destruct logger by end of scope.
+ GrabAndDrop(scoper.Pass());
+ EXPECT_FALSE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+}
+
+TEST(ScopedPtrTest, ReturnTypeBehavior) {
+ int constructed = 0;
+
+ // Test that we can return a scoped_ptr.
+ {
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoped_ptr<ConDecLogger> scoper(logger);
+ EXPECT_EQ(1, constructed);
+
+ PassThru(scoper.Pass());
+ EXPECT_FALSE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Test uncaught return type not leak.
+ {
+ ConDecLogger* logger = new ConDecLogger(&constructed);
+ scoped_ptr<ConDecLogger> scoper(logger);
+ EXPECT_EQ(1, constructed);
+
+ // Should auto-destruct logger by end of scope.
+ PassThru(scoper.Pass());
+ EXPECT_FALSE(scoper.get());
+ }
+ EXPECT_EQ(0, constructed);
+
+ // Call TestReturnOfType() so the compiler doesn't warn for an unused
+ // function.
+ {
+ TestReturnOfType(&constructed);
+ }
+ EXPECT_EQ(0, constructed);
+}
+
+TEST(ScopedPtrTest, CustomDeleter) {
+ double dummy_value; // Custom deleter never touches this value.
+ int deletes = 0;
+ int alternate_deletes = 0;
+
+ // Normal delete support.
+ {
+ deletes = 0;
+ scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
+ CountingDeleter(&deletes));
+ EXPECT_EQ(0, deletes);
+ EXPECT_TRUE(scoper.get());
+ }
+ EXPECT_EQ(1, deletes);
+
+ // Test reset() and release().
+ deletes = 0;
+ {
+ scoped_ptr<double, CountingDeleter> scoper(NULL,
+ CountingDeleter(&deletes));
+ EXPECT_FALSE(scoper.get());
+ EXPECT_FALSE(scoper.release());
+ EXPECT_FALSE(scoper.get());
+ scoper.reset();
+ EXPECT_FALSE(scoper.get());
+ EXPECT_EQ(0, deletes);
+
+ scoper.reset(&dummy_value);
+ scoper.reset();
+ EXPECT_EQ(1, deletes);
+
+ scoper.reset(&dummy_value);
+ EXPECT_EQ(&dummy_value, scoper.release());
+ }
+ EXPECT_EQ(1, deletes);
+
+ // Test get_deleter().
+ deletes = 0;
+ alternate_deletes = 0;
+ {
+ scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
+ CountingDeleter(&deletes));
+ // Call deleter manually.
+ EXPECT_EQ(0, deletes);
+ scoper.get_deleter()(&dummy_value);
+ EXPECT_EQ(1, deletes);
+
+ // Deleter is still there after reset.
+ scoper.reset();
+ EXPECT_EQ(2, deletes);
+ scoper.get_deleter()(&dummy_value);
+ EXPECT_EQ(3, deletes);
+
+ // Deleter can be assigned into (matches C++11 unique_ptr<> spec).
+ scoper.get_deleter() = CountingDeleter(&alternate_deletes);
+ scoper.reset(&dummy_value);
+ EXPECT_EQ(0, alternate_deletes);
+
+ }
+ EXPECT_EQ(3, deletes);
+ EXPECT_EQ(1, alternate_deletes);
+
+ // Test operator= deleter support.
+ deletes = 0;
+ alternate_deletes = 0;
+ {
+ double dummy_value2;
+ scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
+ CountingDeleter(&deletes));
+ scoped_ptr<double, CountingDeleter> scoper2(
+ &dummy_value2,
+ CountingDeleter(&alternate_deletes));
+ EXPECT_EQ(0, deletes);
+ EXPECT_EQ(0, alternate_deletes);
+
+ // Pass the second deleter through a constructor and an operator=. Then
+ // reinitialize the empty scopers to ensure that each one is deleting
+ // properly.
+ scoped_ptr<double, CountingDeleter> scoper3(scoper2.Pass());
+ scoper = scoper3.Pass();
+ EXPECT_EQ(1, deletes);
+
+ scoper2.reset(&dummy_value2);
+ scoper3.reset(&dummy_value2);
+ EXPECT_EQ(0, alternate_deletes);
+
+ }
+ EXPECT_EQ(1, deletes);
+ EXPECT_EQ(3, alternate_deletes);
+
+ // Test swap(), ==, !=, and type-safe Boolean.
+ {
+ scoped_ptr<double, CountingDeleter> scoper1(NULL,
+ CountingDeleter(&deletes));
+ scoped_ptr<double, CountingDeleter> scoper2(NULL,
+ CountingDeleter(&deletes));
+ EXPECT_TRUE(scoper1 == scoper2.get());
+ EXPECT_FALSE(scoper1 != scoper2.get());
+
+ scoper1.reset(&dummy_value);
+ EXPECT_TRUE(scoper1);
+ EXPECT_EQ(&dummy_value, scoper1.get());
+ EXPECT_FALSE(scoper2);
+ EXPECT_FALSE(scoper2.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+
+ scoper2.swap(scoper1);
+ EXPECT_EQ(&dummy_value, scoper2.get());
+ EXPECT_FALSE(scoper1.get());
+ EXPECT_FALSE(scoper1 == scoper2.get());
+ EXPECT_TRUE(scoper1 != scoper2.get());
+ }
+}
+
+// Sanity check test for overloaded new and delete operators. Does not do full
+// coverage of reset/release/Pass() operations as that is redundant with the
+// above.
+TEST(ScopedPtrTest, OverloadedNewAndDelete) {
+ {
+ OverloadedNewAndDelete::ResetCounters();
+ scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
+ EXPECT_TRUE(scoper.get());
+
+ scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass());
+ }
+ EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
+ EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
+}
+
+scoped_ptr<int> NullIntReturn() {
+ return nullptr;
+}
+
+TEST(ScopedPtrTest, Nullptr) {
+ scoped_ptr<int> scoper1(nullptr);
+ scoped_ptr<int> scoper2(new int);
+ scoper2 = nullptr;
+ scoped_ptr<int> scoper3(NullIntReturn());
+ scoped_ptr<int> scoper4 = NullIntReturn();
+ EXPECT_EQ(nullptr, scoper1.get());
+ EXPECT_EQ(nullptr, scoper2.get());
+ EXPECT_EQ(nullptr, scoper3.get());
+ EXPECT_EQ(nullptr, scoper4.get());
+}
+
+scoped_ptr<int[]> NullIntArrayReturn() {
+ return nullptr;
+}
+
+TEST(ScopedPtrTest, NullptrArray) {
+ scoped_ptr<int[]> scoper1(nullptr);
+ scoped_ptr<int[]> scoper2(new int[3]);
+ scoper2 = nullptr;
+ scoped_ptr<int[]> scoper3(NullIntArrayReturn());
+ scoped_ptr<int[]> scoper4 = NullIntArrayReturn();
+ EXPECT_EQ(nullptr, scoper1.get());
+ EXPECT_EQ(nullptr, scoper2.get());
+ EXPECT_EQ(nullptr, scoper3.get());
+ EXPECT_EQ(nullptr, scoper4.get());
+}
+
+class Super {};
+class Sub : public Super {};
+
+scoped_ptr<Sub> SubClassReturn() {
+ return make_scoped_ptr(new Sub);
+}
+
+TEST(ScopedPtrTest, Conversion) {
+ scoped_ptr<Sub> sub1(new Sub);
+ scoped_ptr<Sub> sub2(new Sub);
+
+ // Upcast with Pass() works.
+ scoped_ptr<Super> super1 = sub1.Pass();
+ super1 = sub2.Pass();
+
+ // Upcast with an rvalue works.
+ scoped_ptr<Super> super2 = SubClassReturn();
+ super2 = SubClassReturn();
+}
+
+// Android death tests don't work properly with assert(). Yay.
+#if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
+TEST(ScopedPtrTest, SelfResetAbortsWithDefaultDeleter) {
+ scoped_ptr<int> x(new int);
+ EXPECT_DEATH(x.reset(x.get()), "");
+}
+
+TEST(ScopedPtrTest, SelfResetAbortsWithDefaultArrayDeleter) {
+ scoped_ptr<int[]> y(new int[4]);
+ EXPECT_DEATH(y.reset(y.get()), "");
+}
+
+TEST(ScopedPtrTest, SelfResetAbortsWithDefaultFreeDeleter) {
+ scoped_ptr<int, base::FreeDeleter> z(static_cast<int*>(malloc(sizeof(int))));
+ EXPECT_DEATH(z.reset(z.get()), "");
+}
+
+// A custom deleter that doesn't opt out should still crash.
+TEST(ScopedPtrTest, SelfResetAbortsWithCustomDeleter) {
+ struct CustomDeleter {
+ inline void operator()(int* x) { delete x; }
+ };
+ scoped_ptr<int, CustomDeleter> x(new int);
+ EXPECT_DEATH(x.reset(x.get()), "");
+}
+#endif
+
+TEST(ScopedPtrTest, SelfResetWithCustomDeleterOptOut) {
+ // A custom deleter should be able to opt out of self-reset abort behavior.
+ struct NoOpDeleter {
+#if !defined(NDEBUG)
+ typedef void AllowSelfReset;
+#endif
+ inline void operator()(int*) {}
+ };
+ scoped_ptr<int> owner(new int);
+ scoped_ptr<int, NoOpDeleter> x(owner.get());
+ x.reset(x.get());
+}
+
+// Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
+// value first.
+TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) {
+ scoped_ptr<int> x(new int);
+ std::stringstream s1;
+ s1 << x;
+
+ std::stringstream s2;
+ s2 << x.get();
+
+ EXPECT_EQ(s2.str(), s1.str());
+}
diff --git a/third_party/chromium/base/memory/weak_ptr.cc b/third_party/chromium/base/memory/weak_ptr.cc
new file mode 100644
index 0000000..0f91ef3
--- /dev/null
+++ b/third_party/chromium/base/memory/weak_ptr.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/weak_ptr.h"
+
+namespace base {
+namespace internal {
+
+WeakReference::Flag::Flag() : is_valid_(true) {
+}
+
+void WeakReference::Flag::Invalidate() {
+ is_valid_ = false;
+}
+
+bool WeakReference::Flag::IsValid() const {
+ return is_valid_;
+}
+
+WeakReference::Flag::~Flag() {
+}
+
+WeakReference::WeakReference() {
+}
+
+WeakReference::WeakReference(const Flag* flag) : flag_(flag) {
+}
+
+WeakReference::~WeakReference() {
+}
+
+bool WeakReference::is_valid() const { return flag_.get() && flag_->IsValid(); }
+
+WeakReferenceOwner::WeakReferenceOwner() {
+}
+
+WeakReferenceOwner::~WeakReferenceOwner() {
+ Invalidate();
+}
+
+WeakReference WeakReferenceOwner::GetRef() const {
+ // If we hold the last reference to the Flag then create a new one.
+ if (!HasRefs())
+ flag_ = new WeakReference::Flag();
+
+ return WeakReference(flag_.get());
+}
+
+void WeakReferenceOwner::Invalidate() {
+ if (flag_.get()) {
+ flag_->Invalidate();
+ flag_ = NULL;
+ }
+}
+
+WeakPtrBase::WeakPtrBase() {
+}
+
+WeakPtrBase::~WeakPtrBase() {
+}
+
+WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) {
+}
+
+} // namespace internal
+} // namespace base
diff --git a/third_party/chromium/base/memory/weak_ptr.h b/third_party/chromium/base/memory/weak_ptr.h
new file mode 100644
index 0000000..e07beeb
--- /dev/null
+++ b/third_party/chromium/base/memory/weak_ptr.h
@@ -0,0 +1,336 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Weak pointers are pointers to an object that do not affect its lifetime,
+// and which may be invalidated (i.e. reset to NULL) by the object, or its
+// owner, at any time, most commonly when the object is about to be deleted.
+
+// Weak pointers are useful when an object needs to be accessed safely by one
+// or more objects other than its owner, and those callers can cope with the
+// object vanishing and e.g. tasks posted to it being silently dropped.
+// Reference-counting such an object would complicate the ownership graph and
+// make it harder to reason about the object's lifetime.
+
+// EXAMPLE:
+//
+// class Controller {
+// public:
+// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
+// void WorkComplete(const Result& result) { ... }
+// private:
+// // Member variables should appear before the WeakPtrFactory, to ensure
+// // that any WeakPtrs to Controller are invalidated before its members
+// // variable's destructors are executed, rendering them invalid.
+// WeakPtrFactory<Controller> weak_factory_;
+// };
+//
+// class Worker {
+// public:
+// static void StartNew(const WeakPtr<Controller>& controller) {
+// Worker* worker = new Worker(controller);
+// // Kick off asynchronous processing...
+// }
+// private:
+// Worker(const WeakPtr<Controller>& controller)
+// : controller_(controller) {}
+// void DidCompleteAsynchronousProcessing(const Result& result) {
+// if (controller_)
+// controller_->WorkComplete(result);
+// }
+// WeakPtr<Controller> controller_;
+// };
+//
+// With this implementation a caller may use SpawnWorker() to dispatch multiple
+// Workers and subsequently delete the Controller, without waiting for all
+// Workers to have completed.
+
+// ------------------------- IMPORTANT: Thread-safety -------------------------
+
+// Weak pointers may be passed safely between threads, but must always be
+// dereferenced and invalidated on the same SequencedTaskRunner otherwise
+// checking the pointer would be racey.
+//
+// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
+// is dereferenced, the factory and its WeakPtrs become bound to the calling
+// thread or current SequencedWorkerPool token, and cannot be dereferenced or
+// invalidated on any other task runner. Bound WeakPtrs can still be handed
+// off to other task runners, e.g. to use to post tasks back to object on the
+// bound sequence.
+//
+// Invalidating the factory's WeakPtrs un-binds it from the sequence, allowing
+// it to be passed for a different sequence to use or delete it.
+
+#ifndef BASE_MEMORY_WEAK_PTR_H_
+#define BASE_MEMORY_WEAK_PTR_H_
+
+#include "base/basictypes.h"
+#include "base/base_export.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+
+namespace base {
+
+template <typename T> class SupportsWeakPtr;
+template <typename T> class WeakPtr;
+
+namespace internal {
+// These classes are part of the WeakPtr implementation.
+// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
+
+class BASE_EXPORT WeakReference {
+ public:
+ // Although Flag is bound to a specific SequencedTaskRunner, it may be
+ // deleted from another via base::WeakPtr::~WeakPtr().
+ class Flag : public RefCountedThreadSafe<Flag> {
+ public:
+ Flag();
+
+ void Invalidate();
+ bool IsValid() const;
+
+ private:
+ friend class base::RefCountedThreadSafe<Flag>;
+
+ ~Flag();
+
+ bool is_valid_;
+ };
+
+ WeakReference();
+ explicit WeakReference(const Flag* flag);
+ ~WeakReference();
+
+ bool is_valid() const;
+
+ private:
+ scoped_refptr<const Flag> flag_;
+};
+
+class BASE_EXPORT WeakReferenceOwner {
+ public:
+ WeakReferenceOwner();
+ ~WeakReferenceOwner();
+
+ WeakReference GetRef() const;
+
+ bool HasRefs() const {
+ return flag_.get() && !flag_->HasOneRef();
+ }
+
+ void Invalidate();
+
+ private:
+ mutable scoped_refptr<WeakReference::Flag> flag_;
+};
+
+// This class simplifies the implementation of WeakPtr's type conversion
+// constructor by avoiding the need for a public accessor for ref_. A
+// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
+// base class gives us a way to access ref_ in a protected fashion.
+class BASE_EXPORT WeakPtrBase {
+ public:
+ WeakPtrBase();
+ ~WeakPtrBase();
+
+ protected:
+ explicit WeakPtrBase(const WeakReference& ref);
+
+ WeakReference ref_;
+};
+
+// This class provides a common implementation of common functions that would
+// otherwise get instantiated separately for each distinct instantiation of
+// SupportsWeakPtr<>.
+class SupportsWeakPtrBase {
+ public:
+ // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
+ // conversion will only compile if there is exists a Base which inherits
+ // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
+ // function that makes calling this easier.
+ template<typename Derived>
+ static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
+ typedef std::is_convertible<Derived*, internal::SupportsWeakPtrBase*>
+ convertible;
+ COMPILE_ASSERT(convertible::value,
+ AsWeakPtr_argument_inherits_from_SupportsWeakPtr);
+ return AsWeakPtrImpl<Derived>(t, *t);
+ }
+
+ private:
+ // This template function uses type inference to find a Base of Derived
+ // which is an instance of SupportsWeakPtr<Base>. We can then safely
+ // static_cast the Base* to a Derived*.
+ template <typename Derived, typename Base>
+ static WeakPtr<Derived> AsWeakPtrImpl(
+ Derived* t, const SupportsWeakPtr<Base>&) {
+ WeakPtr<Base> ptr = t->Base::AsWeakPtr();
+ return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));
+ }
+};
+
+} // namespace internal
+
+template <typename T> class WeakPtrFactory;
+
+// The WeakPtr class holds a weak reference to |T*|.
+//
+// This class is designed to be used like a normal pointer. You should always
+// null-test an object of this class before using it or invoking a method that
+// may result in the underlying object being destroyed.
+//
+// EXAMPLE:
+//
+// class Foo { ... };
+// WeakPtr<Foo> foo;
+// if (foo)
+// foo->method();
+//
+template <typename T>
+class WeakPtr : public internal::WeakPtrBase {
+ public:
+ WeakPtr() : ptr_(NULL) {
+ }
+
+ // Allow conversion from U to T provided U "is a" T. Note that this
+ // is separate from the (implicit) copy constructor.
+ template <typename U>
+ WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) {
+ }
+
+ T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
+
+ T& operator*() const {
+ DCHECK(get() != NULL);
+ return *get();
+ }
+ T* operator->() const {
+ DCHECK(get() != NULL);
+ return get();
+ }
+
+ // Allow WeakPtr<element_type> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ //
+ // Note that this trick is only safe when the == and != operators
+ // are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2"
+ // will compile but do the wrong thing (i.e., convert to Testable
+ // and then do the comparison).
+ private:
+ typedef T* WeakPtr::*Testable;
+
+ public:
+ operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; }
+
+ void reset() {
+ ref_ = internal::WeakReference();
+ ptr_ = NULL;
+ }
+
+ private:
+ // Explicitly declare comparison operators as required by the bool
+ // trick, but keep them private.
+ template <class U> bool operator==(WeakPtr<U> const&) const;
+ template <class U> bool operator!=(WeakPtr<U> const&) const;
+
+ friend class internal::SupportsWeakPtrBase;
+ template <typename U> friend class WeakPtr;
+ friend class SupportsWeakPtr<T>;
+ friend class WeakPtrFactory<T>;
+
+ WeakPtr(const internal::WeakReference& ref, T* ptr)
+ : WeakPtrBase(ref),
+ ptr_(ptr) {
+ }
+
+ // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
+ // value is undefined (as opposed to NULL).
+ T* ptr_;
+};
+
+// A class may be composed of a WeakPtrFactory and thereby
+// control how it exposes weak pointers to itself. This is helpful if you only
+// need weak pointers within the implementation of a class. This class is also
+// useful when working with primitive types. For example, you could have a
+// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
+template <class T>
+class WeakPtrFactory {
+ public:
+ explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
+ }
+
+ ~WeakPtrFactory() {
+ ptr_ = NULL;
+ }
+
+ WeakPtr<T> GetWeakPtr() {
+ DCHECK(ptr_);
+ return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
+ }
+
+ // Call this method to invalidate all existing weak pointers.
+ void InvalidateWeakPtrs() {
+ DCHECK(ptr_);
+ weak_reference_owner_.Invalidate();
+ }
+
+ // Call this method to determine if any weak pointers exist.
+ bool HasWeakPtrs() const {
+ DCHECK(ptr_);
+ return weak_reference_owner_.HasRefs();
+ }
+
+ private:
+ internal::WeakReferenceOwner weak_reference_owner_;
+ T* ptr_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
+};
+
+// A class may extend from SupportsWeakPtr to let others take weak pointers to
+// it. This avoids the class itself implementing boilerplate to dispense weak
+// pointers. However, since SupportsWeakPtr's destructor won't invalidate
+// weak pointers to the class until after the derived class' members have been
+// destroyed, its use can lead to subtle use-after-destroy issues.
+template <class T>
+class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
+ public:
+ SupportsWeakPtr() {}
+
+ WeakPtr<T> AsWeakPtr() {
+ return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
+ }
+
+ protected:
+ ~SupportsWeakPtr() {}
+
+ private:
+ internal::WeakReferenceOwner weak_reference_owner_;
+ DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
+};
+
+// Helper function that uses type deduction to safely return a WeakPtr<Derived>
+// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
+// extends a Base that extends SupportsWeakPtr<Base>.
+//
+// EXAMPLE:
+// class Base : public base::SupportsWeakPtr<Producer> {};
+// class Derived : public Base {};
+//
+// Derived derived;
+// base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
+//
+// Note that the following doesn't work (invalid type conversion) since
+// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
+// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
+// the caller.
+//
+// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
+
+template <typename Derived>
+WeakPtr<Derived> AsWeakPtr(Derived* t) {
+ return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
+}
+
+} // namespace base
+
+#endif // BASE_MEMORY_WEAK_PTR_H_
diff --git a/third_party/chromium/base/memory/weak_ptr_unittest.cc b/third_party/chromium/base/memory/weak_ptr_unittest.cc
new file mode 100644
index 0000000..8d4057c
--- /dev/null
+++ b/third_party/chromium/base/memory/weak_ptr_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/weak_ptr.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace base {
+namespace {
+
+struct Base {
+ std::string member;
+};
+struct Derived : public Base {};
+
+struct TargetBase {};
+struct Target : public TargetBase, public SupportsWeakPtr<Target> {
+ virtual ~Target() {}
+};
+struct DerivedTarget : public Target {};
+struct Arrow {
+ WeakPtr<Target> target;
+};
+struct TargetWithFactory : public Target {
+ TargetWithFactory() : factory(this) {}
+ WeakPtrFactory<Target> factory;
+};
+
+} // namespace
+
+TEST(WeakPtrFactoryTest, Basic) {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ WeakPtr<int> ptr = factory.GetWeakPtr();
+ EXPECT_EQ(&data, ptr.get());
+}
+
+TEST(WeakPtrFactoryTest, Comparison) {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ WeakPtr<int> ptr = factory.GetWeakPtr();
+ WeakPtr<int> ptr2 = ptr;
+ EXPECT_EQ(ptr.get(), ptr2.get());
+}
+
+TEST(WeakPtrFactoryTest, OutOfScope) {
+ WeakPtr<int> ptr;
+ EXPECT_EQ(NULL, ptr.get());
+ {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ ptr = factory.GetWeakPtr();
+ }
+ EXPECT_EQ(NULL, ptr.get());
+}
+
+TEST(WeakPtrFactoryTest, Multiple) {
+ WeakPtr<int> a, b;
+ {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ a = factory.GetWeakPtr();
+ b = factory.GetWeakPtr();
+ EXPECT_EQ(&data, a.get());
+ EXPECT_EQ(&data, b.get());
+ }
+ EXPECT_EQ(NULL, a.get());
+ EXPECT_EQ(NULL, b.get());
+}
+
+TEST(WeakPtrFactoryTest, MultipleStaged) {
+ WeakPtr<int> a;
+ {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ a = factory.GetWeakPtr();
+ {
+ WeakPtr<int> b = factory.GetWeakPtr();
+ }
+ EXPECT_TRUE(NULL != a.get());
+ }
+ EXPECT_EQ(NULL, a.get());
+}
+
+TEST(WeakPtrFactoryTest, Dereference) {
+ Base data;
+ data.member = "123456";
+ WeakPtrFactory<Base> factory(&data);
+ WeakPtr<Base> ptr = factory.GetWeakPtr();
+ EXPECT_EQ(&data, ptr.get());
+ EXPECT_EQ(data.member, (*ptr).member);
+ EXPECT_EQ(data.member, ptr->member);
+}
+
+TEST(WeakPtrFactoryTest, UpCast) {
+ Derived data;
+ WeakPtrFactory<Derived> factory(&data);
+ WeakPtr<Base> ptr = factory.GetWeakPtr();
+ ptr = factory.GetWeakPtr();
+ EXPECT_EQ(ptr.get(), &data);
+}
+
+TEST(WeakPtrTest, SupportsWeakPtr) {
+ Target target;
+ WeakPtr<Target> ptr = target.AsWeakPtr();
+ EXPECT_EQ(&target, ptr.get());
+}
+
+TEST(WeakPtrTest, DerivedTarget) {
+ DerivedTarget target;
+ WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
+ EXPECT_EQ(&target, ptr.get());
+}
+
+TEST(WeakPtrTest, InvalidateWeakPtrs) {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ WeakPtr<int> ptr = factory.GetWeakPtr();
+ EXPECT_EQ(&data, ptr.get());
+ EXPECT_TRUE(factory.HasWeakPtrs());
+ factory.InvalidateWeakPtrs();
+ EXPECT_EQ(NULL, ptr.get());
+ EXPECT_FALSE(factory.HasWeakPtrs());
+
+ // Test that the factory can create new weak pointers after a
+ // InvalidateWeakPtrs call, and they remain valid until the next
+ // InvalidateWeakPtrs call.
+ WeakPtr<int> ptr2 = factory.GetWeakPtr();
+ EXPECT_EQ(&data, ptr2.get());
+ EXPECT_TRUE(factory.HasWeakPtrs());
+ factory.InvalidateWeakPtrs();
+ EXPECT_EQ(NULL, ptr2.get());
+ EXPECT_FALSE(factory.HasWeakPtrs());
+}
+
+TEST(WeakPtrTest, HasWeakPtrs) {
+ int data;
+ WeakPtrFactory<int> factory(&data);
+ {
+ WeakPtr<int> ptr = factory.GetWeakPtr();
+ EXPECT_TRUE(factory.HasWeakPtrs());
+ }
+ EXPECT_FALSE(factory.HasWeakPtrs());
+}
+
+} // namespace base