Index: base/memory/pass_scoped_ptr.h |
diff --git a/base/memory/pass_scoped_ptr.h b/base/memory/pass_scoped_ptr.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1adc4367fd3af3017b56d2bc75f02784003a188a |
--- /dev/null |
+++ b/base/memory/pass_scoped_ptr.h |
@@ -0,0 +1,211 @@ |
+// 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. |
+ |
+#ifndef BASE_MEMORY_PASS_SCOPED_PTR_H_ |
+#define BASE_MEMORY_PASS_SCOPED_PTR_H_ |
+#pragma once |
+ |
+#include <stddef.h> |
+ |
+#include "base/compiler_specific.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/gtest_prod_util.h" |
+ |
+namespace base { |
+ |
+// Forward Decls for friending. |
+template <typename T> class PassScopedPtr; |
+template <typename T> PassScopedPtr<T> MakePassScopedPtr(T* ptr); |
+ |
+namespace internal { |
+template <bool IsWeakCall, typename ReturnType, typename Runnable, |
+ typename ArgsType> |
+struct InvokeHelper; |
+} // namespace internal |
+ |
+namespace subtle { |
+ |
+// When a PassScopedPtr<> is created based off of the Anchor Type, deleting the |
+// PassScopedPtr<> will not delete the pointee. This is used in base::Bind() so |
+// that a Callback<> with a PassScopedPtr<> only gains ownership of the pointee |
+// if it explicitly calls Pass(). |
+template <typename T> |
+class PassScopedPtrAnchor { |
+ public: |
+ explicit PassScopedPtrAnchor(PassScopedPtr<T> ptr) |
+ : ptr_(ptr.Pass()) { |
+ } |
+ |
+ PassScopedPtrAnchor(const PassScopedPtrAnchor& other) |
+ : ptr_(const_cast<PassScopedPtrAnchor&>(other).ptr_.Pass()){ |
+ } |
+ |
+ T* Release() { |
+ return ptr_.Release(); |
+ } |
+ |
+ bool is_valid() { return ptr_.is_valid(); } |
+ |
+ private: |
+ PassScopedPtr<T> ptr_; |
+}; |
+ |
+} // namespace subtle |
+ |
+// PassScopedPtr is a container class that is targeted specifically at |
+// transfering ownership across function calls. It should only be used as |
+// a parameter type, and the parameter type must be a const reference. If |
+// a function is returning ownership, it should use |
+// PassScopedPtr<T>. All other situations should prefer |
+// scoped_ptr. |
+// |
+// To help prevent unwanted usage, the public interface of this class is |
+// intentionally featureless lacking overrides for ->, or easy retrieval to |
+// the underlying pointer. In particular, only 3 operations are allowed for |
+// the class: |
+// |
+// 1) Calling Pass() to transfer ownership to another PassScopedPtr. |
+// 2) Calling PassForBind() to transfer ownership to a Bind() call. |
+// 3) Calling ToScopedPtr() to transfer ownership to a scoped_ptr. |
+// |
+// Each of these methods may only be called once on a PassScopedPtr. A second |
+// invocation will cause a CHECK(). |
+// |
+// This class is not thread safe. If passing across threads, external |
+// synchronization must be used. One exception is that it is safe to use |
+// with base::Bind() to pass through threads via a PostTask because the |
+// PostTask's mutex will enforce the correct synchronization as long as |
+// that only one thread may invoke Run() on the resulting base::Callback(). |
+// |
+// In the case that the resulting base::Callback<> is executed multiple times |
+// it will be given the same logical PassScopedPtr as the argument. |
+// Ownership of the underlying pointer is kept with the base::Callback until |
+// Pass() or ToScopedPtr() is executed during one of these calls. After this, |
+// ownership is passed, and subsequent calls will get a PassScopedPtr where |
+// is_valid() returns false. This makes the transfer of ownership _out_ of |
+// a base::Callback's bound argument explicit. |
+template <class T> |
+class PassScopedPtr { |
+ public: |
+ // Destructor. If there is a T object, delete it. |
+ // We don't need to test value_.raw_ptr == NULL because C++ does that for us. |
+ ~PassScopedPtr() { |
+ if (type_ == TYPE_RAW) { |
+ enum { type_must_be_complete = sizeof(T) }; |
+ delete value_.raw_ptr; |
+ } |
+ } |
+ |
+ // Returns true if this object can be copied, or ToScopedPtr() can be called. |
+ bool is_valid() const { return type_ != TYPE_INVALID; } |
+ |
+ void ToScopedPtr(scoped_ptr<T>* scoped) const { |
+ scoped->reset(Release()); |
+ } |
+ |
+ PassScopedPtr Pass() { |
+ return PassScopedPtr(MoveProxy(*this)); |
+ } |
+ |
+ // Only to be used in conjunction with a Bind() call. |
+ subtle::PassScopedPtrAnchor<T> PassForBind() { |
+ return subtle::PassScopedPtrAnchor<T>(Pass()); |
+ } |
+ |
+ // ==== Begin implementation of Move semantics in C++03. |
+ // |
+ // http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor |
+ private: |
+ struct MoveProxy { |
+ explicit MoveProxy(PassScopedPtr& obj) : obj_(obj) {} |
+ PassScopedPtr& obj_; |
+ }; |
+ // Important that this does NOT take a const PassScopedPtr&. |
+ PassScopedPtr(PassScopedPtr& other) {} |
+ public: |
+ operator MoveProxy() { |
+ return MoveProxy(*this); |
+ } |
+ PassScopedPtr(MoveProxy proxy) : type_(TYPE_RAW) { |
+ value_.raw_ptr = proxy.obj_.Release(); |
+ } |
+ // ==== End implementation of Move semantics in C++03. |
+ |
+ private: |
+ FRIEND_TEST(PassScopedPtrTest, AnchorBehavior); |
+ FRIEND_TEST(PassScopedPtrTest, BasicMethods); |
+ template <bool IsWeakCall, typename ReturnType, typename Runnable, |
+ typename ArgsType> |
+ friend struct internal::InvokeHelper; |
+ friend PassScopedPtr MakePassScopedPtr<T>(T* ptr); |
+ friend class subtle::PassScopedPtrAnchor<T>; |
+ |
+ enum Type { |
+ TYPE_INVALID, |
+ TYPE_RAW, |
+ TYPE_ANCHORED, |
+ }; |
+ |
+ explicit PassScopedPtr(T* ptr) |
+ : type_(TYPE_RAW) { |
+ value_.raw_ptr = ptr; |
+ } |
+ |
+ PassScopedPtr(subtle::PassScopedPtrAnchor<T>* anchor) { |
+ if (anchor->is_valid()) { |
+ type_ = TYPE_ANCHORED; |
+ value_.anchor_ptr = anchor; |
+ } else { |
+ type_ = TYPE_INVALID; |
+ value_.anchor_ptr = NULL; |
+ } |
+ } |
+ |
+ T* Release() const { |
+ // Make sure pointer has not been used already. |
+ CHECK(type_ != TYPE_INVALID); |
+ |
+ T* ret_val = NULL; |
+ if (type_ == TYPE_RAW) { |
+ ret_val = value_.raw_ptr; |
+ value_.raw_ptr = NULL; |
+ } else { |
+ ret_val = value_.anchor_ptr->Release(); |
+ } |
+ |
+ type_ = TYPE_INVALID; |
+ return ret_val; |
+ } |
+ |
+ // Is set after ToScopedPtr() is called. After this, subsequent calls to |
+ // ToScopedPtr() will fail. This ensures that ToScopedPtr() is only ever |
+ // called once per object. |
+ mutable Type type_; |
+ |
+ // The actual value that is carried. |
+ mutable union { |
+ T* raw_ptr; |
+ subtle::PassScopedPtrAnchor<T>* anchor_ptr; |
+ } value_; |
+ |
+ // Forbid comparison of PassScopedPtr 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 PassScopedPtr. |
+ template <class U> bool operator==(const PassScopedPtr<U>& rhs) const; |
+ template <class U> bool operator!=(const PassScopedPtr<U>& rhs) const; |
+ |
+ // Forbid the assignment operator. |
+ template <class U> |
+ const PassScopedPtr<U>& operator=(const PassScopedPtr<U>& rhs) const; |
+}; |
+ |
+template <typename T> |
+PassScopedPtr<T> MakePassScopedPtr(T* ptr) { |
+ return PassScopedPtr<T>(ptr).Pass(); |
+} |
+ |
+} // namespace base |
+ |
+#endif // BASE_MEMORY_PASS_SCOPED_PTR_H_ |