diff options
Diffstat (limited to 'base/bind_helpers.h')
-rw-r--r-- | base/bind_helpers.h | 152 |
1 files changed, 31 insertions, 121 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h index df8cf82..6e0f8fe 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -6,29 +6,19 @@ // 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::Owned(), bass::Passed(), -// base::ConstRef(), and base::IgnoreResult(). +// The public functions are base::Unretained(), base::Owned(), +// base::ConstRef(), and base::IgnoreReturn(). // // 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. -// -// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) -// through a Callback. Logically, this signifies a destructive transfer of -// the state of the argument into the target function. Invoking -// Callback::Run() twice on a Callback that was created with a Passed() -// argument will CHECK() because the first invocation would have already -// transferred ownership to the target function. -// // 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 +// a Closure. This is useful if you need to PostTask with a function that has +// a return value that you don't care about. // -// IgnoreResult() is used to adapt a function or Callback with a return type to -// one with a void return. This is most useful if you have a function with, -// say, a pesky ignorable bool return that you want to use with PostTask or -// something else that expect a Callback with a void return. // // EXAMPLE OF Unretained(): // @@ -85,45 +75,13 @@ // its bound callbacks. // // -// EXAMPLE OF IgnoreResult(): +// EXAMPLE OF IgnoreReturn(): // // int DoSomething(int arg) { cout << arg << endl; } -// -// // Assign to a Callback with a void return type. -// Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething)); -// cb->Run(1); // Prints "1". -// -// // Prints "1" on |ml|. -// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); -// -// -// EXAMPLE OF Passed(): -// -// void TakesOwnership(scoped_ptr<Foo> arg) { } -// scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } -// -// scoped_ptr<Foo> f(new Foo()); -// -// // |cb| is given ownership of Foo(). |f| is now NULL. -// // You can use f.Pass() in place of &f, but it's more verbose. -// Closure cb = Bind(&TakesOwnership, Passed(&f)); -// -// // Run was never called so |cb| still owns Foo() and deletes -// // it on Reset(). -// cb.Reset(); -// -// // |cb| is given a new Foo created by CreateFoo(). -// cb = Bind(&TakesOwnership, Passed(CreateFoo())); -// -// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| -// // no longer owns Foo() and, if reset, would not delete Foo(). -// cb.Run(); // Foo() is now transferred to |arg| and deleted. -// cb.Run(); // This CHECK()s since Foo() already been used once. -// -// Passed() is particularly useful with PostTask() when you are transferring -// ownership of an argument into a task, but don't necessarily know if the -// task will always be executed. This can happen if the task is cancellable -// or if it is posted to a MessageLoopProxy. +// Callback<int(void)> cb = Bind(&DoSomething, 1); +// Closure c = IgnoreReturn(cb); // Prints "1" +// or +// ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| #ifndef BASE_BIND_HELPERS_H_ #define BASE_BIND_HELPERS_H_ @@ -329,45 +287,6 @@ class OwnedWrapper { mutable T* ptr_; }; -// PassedWrapper is a copyable adapter for a scoper that ignores const. -// -// It is needed to get around the fact that Bind() takes a const reference to -// all its arguments. Because Bind() takes a const reference to avoid -// unnecessary copies, it is incompatible with movable-but-not-copyable -// types; doing a destructive "move" of the type into Bind() would violate -// the const correctness. -// -// This conundrum cannot be solved without either C++11 rvalue references or -// a O(2^n) blowup of Bind() templates to handle each combination of regular -// types and movable-but-not-copyable types. Thus we introduce a wrapper type -// that is copyable to transmit the correct type information down into -// BindState<>. Ignoring const in this type makes sense because it is only -// created when we are explicitly trying to do a destructive move. -// -// Two notes: -// 1) PassedWrapper supports any type that has a "Pass()" function. -// This is intentional. The whitelisting of which specific types we -// support is maintained by CallbackParamTraits<>. -// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" -// scoper to a Callback and allow the Callback to execute once. -template <typename T> -class PassedWrapper { - public: - explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { - } - T Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return scoper_.Pass(); - } - - private: - mutable bool is_valid_; - mutable T scoper_; -}; - // Unwrap the stored parameters for the wrappers above. template <typename T> struct UnwrapTraits { @@ -411,17 +330,9 @@ struct UnwrapTraits<OwnedWrapper<T> > { } }; -template <typename T> -struct UnwrapTraits<PassedWrapper<T> > { - typedef T ForwardType; - static T Unwrap(PassedWrapper<T>& o) { - return o.Pass(); - } -}; - // Utility for handling different refcounting semantics in the Bind() // function. -template <bool is_method, typename T> +template <bool, typename T> struct MaybeRefcount; template <typename T> @@ -437,17 +348,23 @@ struct MaybeRefcount<false, T[n]> { }; template <typename T> -struct MaybeRefcount<true, T> { - static void AddRef(const T&) {} - static void Release(const T&) {} -}; - -template <typename T> struct MaybeRefcount<true, T*> { static void AddRef(T* o) { o->AddRef(); } static void Release(T* o) { o->Release(); } }; +template <typename T> +struct MaybeRefcount<true, UnretainedWrapper<T> > { + static void AddRef(const UnretainedWrapper<T>&) {} + static void Release(const UnretainedWrapper<T>&) {} +}; + +template <typename T> +struct MaybeRefcount<true, 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 // scoped_refptr<> inside the storage object already. template <typename T> @@ -462,13 +379,19 @@ struct MaybeRefcount<true, const T*> { static void Release(const T* o) { o->Release(); } }; +template <typename T> +struct MaybeRefcount<true, WeakPtr<T> > { + static void AddRef(const WeakPtr<T>&) {} + static void Release(const WeakPtr<T>&) {} +}; + template <typename R> void VoidReturnAdapter(Callback<R(void)> callback) { callback.Run(); } // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a -// method. It is used internally by Bind() to select the correct +// method. It is unsed internally by Bind() to select the correct // InvokeHelper that will no-op itself in the event the WeakPtr<> for // the target object is invalidated. // @@ -499,20 +422,6 @@ static inline internal::OwnedWrapper<T> Owned(T* o) { return internal::OwnedWrapper<T>(o); } -// We offer 2 syntaxes for calling Passed(). The first takes a temporary and -// is best suited for use with the return value of a function. The second -// takes a pointer to the scoper and is just syntactic sugar to avoid having -// to write Passed(scoper.Pass()). -template <typename T> -static inline internal::PassedWrapper<T> Passed(T scoper) { - return internal::PassedWrapper<T>(scoper.Pass()); -} -template <typename T> -static inline internal::PassedWrapper<T> Passed(T* scoper) { - return internal::PassedWrapper<T>(scoper->Pass()); -} - -// -- DEPRECATED -- Use IgnoreResult instead. template <typename R> static inline Closure IgnoreReturn(Callback<R(void)> callback) { return Bind(&internal::VoidReturnAdapter<R>, callback); @@ -529,6 +438,7 @@ IgnoreResult(const Callback<T>& data) { return internal::IgnoreResultHelper<Callback<T> >(data); } + } // namespace base #endif // BASE_BIND_HELPERS_H_ |