diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-15 00:34:42 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-15 00:34:42 +0000 |
commit | 08aa45582008401caac799bfd1faaef510c27d6c (patch) | |
tree | ce783908b5e6080c0860b28efe6bb5cd58e7a6f1 /base/bind_helpers.h | |
parent | bdae981ec7c7206a631d1b27ad3151df7429c584 (diff) | |
download | chromium_src-08aa45582008401caac799bfd1faaef510c27d6c.zip chromium_src-08aa45582008401caac799bfd1faaef510c27d6c.tar.gz chromium_src-08aa45582008401caac799bfd1faaef510c27d6c.tar.bz2 |
Add in an Owned() wrapper to base::Bind().
This allows expression of ownership of a pointer by a callback. It's basically a "scoped_ptr<>" for Callback where the scope tied to the callback object.
BUG=96118
TEST=new unittests.
Review URL: http://codereview.chromium.org/8209001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105622 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/bind_helpers.h')
-rw-r--r-- | base/bind_helpers.h | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h index 07f11f9..d7ddb2c 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -6,10 +6,13 @@ // can be used specify the refcounting and reference semantics of arguments // that are bound by the Bind() function in base/bind.h. // -// The public functions are base::Unretained(), base::ConstRef(), and -// base::IgnoreReturn(). +// The public functions are base::Unretained(), base::Owned(), +// base::ConstRef(), and base::IgnoreReturn(). // -// Unretained() allows Bind() to bind a non-refcounted class. +// Unretained() allows Bind() to bind a non-refcounted class, and to disable +// refcounting on arguments that are refcounted objects. +// Owned() transfers ownership of an object to the Callback resulting from +// bind; the object will be deleted when the Callback is deleted. // ConstRef() allows binding a constant reference to an argument rather // than a copy. // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to @@ -26,7 +29,7 @@ // // // In some function somewhere. // Foo foo; -// Callback<void(void)> foo_callback = +// Closure foo_callback = // Bind(&Foo::func, Unretained(&foo)); // foo_callback.Run(); // Prints "Foo:f". // @@ -34,12 +37,32 @@ // to compile because Foo does not support the AddRef() and Release() methods. // // +// EXAMPLE OF Owned(): +// +// void foo(int* arg) { cout << *arg << endl } +// +// int* pn = new int(1); +// Closure foo_callback = Bind(&foo, Owned(pn)); +// +// foo_callback.Run(); // Prints "1" +// foo_callback.Run(); // Prints "1" +// *n = 2; +// foo_callback.Run(); // Prints "2" +// +// foo_callback.Reset(); // |pn| is deleted. Also will happen when +// // |foo_callback| goes out of scope. +// +// Without Owned(), someone would have to know to delete |pn| when the last +// reference to the Callback is deleted. +// +// // EXAMPLE OF ConstRef(): +// // void foo(int arg) { cout << arg << endl } // // int n = 1; -// Callback<void(void)> no_ref = Bind(&foo, n); -// Callback<void(void)> has_ref = Bind(&foo, ConstRef(n)); +// Closure no_ref = Bind(&foo, n); +// Closure has_ref = Bind(&foo, ConstRef(n)); // // no_ref.Run(); // Prints "1" // has_ref.Run(); // Prints "1" @@ -53,6 +76,7 @@ // // // EXAMPLE OF IgnoreReturn(): +// // int DoSomething(int arg) { cout << arg << endl; } // Callback<int(void)> cb = Bind(&DoSomething, 1); // Closure c = IgnoreReturn(cb); // Prints "1" @@ -199,21 +223,43 @@ struct UnsafeBindtoRefCountedArg<T*> template <typename T> class UnretainedWrapper { public: - explicit UnretainedWrapper(T* o) : obj_(o) {} - T* get() { return obj_; } + explicit UnretainedWrapper(T* o) : ptr_(o) {} + T* get() const { return ptr_; } private: - T* obj_; + T* ptr_; }; template <typename T> class ConstRefWrapper { public: explicit ConstRefWrapper(const T& o) : ptr_(&o) {} - const T& get() { return *ptr_; } + const T& get() const { return *ptr_; } private: const T* ptr_; }; +// An alternate implementation is to avoid the destructive copy, and instead +// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to +// a class that is essentially a scoped_ptr<>. +// +// The current implementation has the benefit though of leaving ParamTraits<> +// fully in callback_internal.h as well as avoiding type conversions during +// storage. +template <typename T> +class OwnedWrapper { + public: + explicit OwnedWrapper(T* o) : ptr_(o) {} + ~OwnedWrapper() { delete ptr_; } + T* get() const { return ptr_; } + OwnedWrapper(const OwnedWrapper& other) { + ptr_ = other.ptr_; + other.ptr_ = NULL; + } + + private: + mutable T* ptr_; +}; + // Unwrap the stored parameters for the wrappers above. template <typename T> @@ -233,6 +279,11 @@ T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } template <typename T> const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } +template <typename T> +T* Unwrap(const OwnedWrapper<T>& o) { + return o.get(); +} + // Utility for handling different refcounting semantics in the Bind() // function. template <typename IsMethod, typename T> @@ -251,15 +302,21 @@ struct MaybeRefcount<base::false_type, T[n]> { }; template <typename T> +struct MaybeRefcount<base::true_type, T*> { + static void AddRef(T* o) { o->AddRef(); } + static void Release(T* o) { o->Release(); } +}; + +template <typename T> struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { static void AddRef(const UnretainedWrapper<T>&) {} static void Release(const UnretainedWrapper<T>&) {} }; template <typename T> -struct MaybeRefcount<base::true_type, T*> { - static void AddRef(T* o) { o->AddRef(); } - static void Release(T* o) { o->Release(); } +struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { + static void AddRef(const OwnedWrapper<T>&) {} + static void Release(const OwnedWrapper<T>&) {} }; // No need to additionally AddRef() and Release() since we are storing a @@ -299,6 +356,11 @@ inline internal::ConstRefWrapper<T> ConstRef(const T& o) { return internal::ConstRefWrapper<T>(o); } +template <typename T> +inline internal::OwnedWrapper<T> Owned(T* o) { + return internal::OwnedWrapper<T>(o); +} + template <typename R> Closure IgnoreReturn(Callback<R(void)> callback) { return Bind(&internal::VoidReturnAdapter<R>, callback); |