| Index: base/callback.h
|
| diff --git a/base/callback.h b/base/callback.h
|
| index e5ea7716b10ab236caaa7df54aff51fd8b89df14..05a7182c3d07c175230ef274f7c55afdf46db340 100644
|
| --- a/base/callback.h
|
| +++ b/base/callback.h
|
| @@ -1,4 +1,9 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| +// This file was GENERATED by command:
|
| +// pump.py callback.h.pump
|
| +// DO NOT EDIT BY HAND!!!
|
| +
|
| +
|
| +// 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.
|
|
|
| @@ -6,249 +11,472 @@
|
| #define BASE_CALLBACK_H_
|
| #pragma once
|
|
|
| -#include "base/tuple.h"
|
| -#include "base/raw_scoped_refptr_mismatch_checker.h"
|
| -
|
| -// Callback --------------------------------------------------------------------
|
| -//
|
| -// A Callback is like a Task but with unbound parameters. It is basically an
|
| -// object-oriented function pointer.
|
| -//
|
| -// Callbacks are designed to work with Tuples. A set of helper functions and
|
| -// classes is provided to hide the Tuple details from the consumer. Client
|
| -// code will generally work with the CallbackRunner base class, which merely
|
| -// provides a Run method and is returned by the New* functions. This allows
|
| -// users to not care which type of class implements the callback, only that it
|
| -// has a certain number and type of arguments.
|
| -//
|
| -// The implementation of this is done by CallbackImpl, which inherits
|
| -// CallbackStorage to store the data. This allows the storage of the data
|
| -// (requiring the class type T) to be hidden from users, who will want to call
|
| -// this regardless of the implementor's type T.
|
| -//
|
| -// Note that callbacks currently have no facility for cancelling or abandoning
|
| -// them. We currently handle this at a higher level for cases where this is
|
| -// necessary. The pointer in a callback must remain valid until the callback
|
| -// is made.
|
| -//
|
| -// Like Task, the callback executor is responsible for deleting the callback
|
| -// pointer once the callback has executed.
|
| -//
|
| -// Example client usage:
|
| -// void Object::DoStuff(int, string);
|
| -// Callback2<int, string>::Type* callback =
|
| -// NewCallback(obj, &Object::DoStuff);
|
| -// callback->Run(5, string("hello"));
|
| -// delete callback;
|
| -// or, equivalently, using tuples directly:
|
| -// CallbackRunner<Tuple2<int, string> >* callback =
|
| -// NewCallback(obj, &Object::DoStuff);
|
| -// callback->RunWithParams(MakeTuple(5, string("hello")));
|
| -//
|
| -// There is also a 0-args version that returns a value. Example:
|
| -// int Object::GetNextInt();
|
| -// CallbackWithReturnValue<int>::Type* callback =
|
| -// NewCallbackWithReturnValue(obj, &Object::GetNextInt);
|
| -// int next_int = callback->Run();
|
| -// delete callback;
|
| -
|
| -// Base for all Callbacks that handles storage of the pointers.
|
| -template <class T, typename Method>
|
| -class CallbackStorage {
|
| - public:
|
| - CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
|
| - }
|
| -
|
| - protected:
|
| - T* obj_;
|
| - Method meth_;
|
| -};
|
| +#include "base/callback_helpers.h"
|
| +#include "base/callback_old.h"
|
|
|
| -// Interface that is exposed to the consumer, that does the actual calling
|
| -// of the method.
|
| -template <typename Params>
|
| -class CallbackRunner {
|
| +// New, super-duper, unified Callback system. This will eventually replace
|
| +// NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
|
| +// systems currently in the Chromium code base.
|
| +//
|
| +// WHAT IS THIS:
|
| +//
|
| +// The templated Callback class is a generalized function object. Together
|
| +// with the Bind() function in bind.h, they provide a type-safe method for
|
| +// performing currying of arguments, and creating a "closure."
|
| +//
|
| +// In programing languages, a closure is a first-class function where all its
|
| +// parameters have been bound (usually via currying). Closures are well
|
| +// suited for representing, and passing around a unit of delayed execution.
|
| +// They are used in Chromium code to schedule tasks on different MessageLoops.
|
| +//
|
| +//
|
| +// MEMORY MANAGEMENT AND PASSING
|
| +//
|
| +// The Callback objects themselves should be passed by const-reference, and
|
| +// stored by copy. They internally store their state via a refcounted class
|
| +// and thus do not need to be deleted.
|
| +//
|
| +// The reason to pass via a const-reference is to avoid unnecessary
|
| +// AddRef/Release pairs to the internal state.
|
| +//
|
| +//
|
| +// EXAMPLE USAGE:
|
| +//
|
| +// /* Binding a normal function. */
|
| +// int Return5() { return 5; }
|
| +// base::Callback<int(int)> func_cb = base::Bind(&Return5);
|
| +// LOG(INFO) << func_cb.Run(5); // Prints 5.
|
| +//
|
| +// void PrintHi() { LOG(INFO) << "hi."; }
|
| +// base::Closure void_func_cb = base::Bind(&PrintHi);
|
| +// LOG(INFO) << void_func_cb.Run(); // Prints: hi.
|
| +//
|
| +// /* Binding a class method. */
|
| +// class Ref : public RefCountedThreadSafe<Ref> {
|
| +// public:
|
| +// int Foo() { return 3; }
|
| +// void PrintBye() { LOG(INFO) << "bye."; }
|
| +// };
|
| +// scoped_refptr<Ref> ref = new Ref();
|
| +// base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
|
| +// LOG(INFO) << ref_cb.Run(); // Prints out 3.
|
| +//
|
| +// base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
|
| +// void_ref_cb.Run(); // Prints: bye.
|
| +//
|
| +// /* Binding a class method in a non-refcounted class.
|
| +// *
|
| +// * WARNING: You must be sure the referee outlives the callback!
|
| +// * This is particularly important if you post a closure to a
|
| +// * MessageLoop because then it becomes hard to know what the
|
| +// * lifetime of the referee needs to be.
|
| +// */
|
| +// class NoRef {
|
| +// public:
|
| +// int Foo() { return 4; }
|
| +// void PrintWhy() { LOG(INFO) << "why???"; }
|
| +// };
|
| +// NoRef no_ref;
|
| +// base::Callback<int(void)> base::no_ref_cb =
|
| +// base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
|
| +// LOG(INFO) << ref_cb.Run(); // Prints out 4.
|
| +//
|
| +// base::Closure void_no_ref_cb =
|
| +// base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
|
| +// void_no_ref_cb.Run(); // Prints: why???
|
| +//
|
| +// /* Binding a reference. */
|
| +// int Identity(int n) { return n; }
|
| +// int value = 1;
|
| +// base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
|
| +// base::Callback<int(void)> bound_ref_cb =
|
| +// base::Bind(&Identity, base::ConstRef(value));
|
| +// LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
|
| +// LOG(INFO) << bound_ref_cb.Run(); // Prints 1.
|
| +// value = 2;
|
| +// LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
|
| +// LOG(INFO) << bound_ref_cb.Run(); // Prints 2.
|
| +//
|
| +//
|
| +// WHERE IS THIS DESIGN FROM:
|
| +//
|
| +// The design Callback and Bind is heavily influenced by C++'s
|
| +// tr1::function/tr1::bind, and by the "Google Callback" system used inside
|
| +// Google.
|
| +//
|
| +//
|
| +// HOW THE IMPLEMENTATION WORKS:
|
| +//
|
| +// There are three main components to the system:
|
| +// 1) The Callback classes.
|
| +// 2) The Bind() functions.
|
| +// 3) The arguments wrappers (eg., Unretained() and ConstRef()).
|
| +//
|
| +// The Callback classes represent a generic function pointer. Internally,
|
| +// it stores a refcounted piece of state that represents the target function
|
| +// and all its bound parameters. Each Callback specialization has a templated
|
| +// constructor that takes an InvokerStorageHolder<> object. In the context of
|
| +// the constructor, the static type of this InvokerStorageHolder<> object
|
| +// uniquely identifies the function it is representing, all its bound
|
| +// parameters, and a DoInvoke() that is capable of invoking the target.
|
| +//
|
| +// Callback's constructor is takes the InvokerStorageHolder<> that has the
|
| +// full static type and erases the target function type, and the bound
|
| +// parameters. It does this by storing a pointer to the specific DoInvoke()
|
| +// function, and upcasting the state of InvokerStorageHolder<> to a
|
| +// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
|
| +// is only used with the stored DoInvoke() pointer.
|
| +//
|
| +// To create InvokerStorageHolder<> objects, we use the Bind() functions.
|
| +// These functions, along with a set of internal templates, are reponsible for
|
| +//
|
| +// - Unwrapping the function signature into return type, and parameters
|
| +// - Determining the number of parameters that are bound
|
| +// - Creating the storage for the bound parameters
|
| +// - Performing compile-time asserts to avoid error-prone behavior
|
| +// - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity
|
| +// matching the number of unbound parameters, and knows the correct
|
| +// refcounting semantics for the target object if we are binding a class
|
| +// method.
|
| +//
|
| +// The Bind functions do the above using type-inference, and template
|
| +// specializations.
|
| +//
|
| +// By default Bind() will store copies of all bound parameters, and attempt
|
| +// to refcount a target object if the function being bound is a class method.
|
| +//
|
| +// To change this behavior, we introduce a set of argument wrappers
|
| +// (eg. Unretained(), and ConstRef()). These are simple container templates
|
| +// that are passed by value, and wrap a pointer to argument. See the
|
| +// file-level comment in base/bind_helpers.h for more info.
|
| +//
|
| +// These types are passed to the Unwrap() functions, and the MaybeRefcount()
|
| +// functions respectively to modify the behavior of Bind(). The Unwrap()
|
| +// and MaybeRefcount() functions change behavior by doing partial
|
| +// specialization based on whether or not a parameter is a wrapper type.
|
| +//
|
| +// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium.
|
| +//
|
| +//
|
| +// WHY NOT TR1 FUNCTION/BIND?
|
| +//
|
| +// Direct use of tr1::function and tr1::bind was considered, but ultimately
|
| +// rejected because of the number of copy constructors invocations involved
|
| +// in the binding of arguments during construction, and the forwarding of
|
| +// arguments during invocation. These copies will no longer be an issue in
|
| +// C++0x because C++0x will support rvalue reference allowing for the compiler
|
| +// to avoid these copies. However, waiting for C++0x is not an option.
|
| +//
|
| +// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
|
| +// tr1::bind call itself will invoke a non-trivial copy constructor three times
|
| +// for each bound parameter. Also, each when passing a tr1::function, each
|
| +// bound argument will be copied again.
|
| +//
|
| +// In addition to the copies taken at binding and invocation, copying a
|
| +// tr1::function causes a copy to be made of all the bound parameters and
|
| +// state.
|
| +//
|
| +// Furthermore, in Chromium, it is desirable for the Callback to take a
|
| +// reference on a target object when representing a class method call. This
|
| +// is not supported by tr1.
|
| +//
|
| +// Lastly, tr1::function and tr1::bind has a more general and flexible API.
|
| +// This includes things like argument reordering by use of
|
| +// tr1::bind::placeholder, support for non-const reference parameters, and some
|
| +// limited amount of subtyping of the tr1::function object (eg.,
|
| +// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
|
| +//
|
| +// These are not features that are required in Chromium. Some of them, such as
|
| +// allowing for reference parameters, and subtyping of functions, may actually
|
| +// because a source of errors. Removing support for these features actually
|
| +// allows for a simpler implementation, and a terser Currying API.
|
| +//
|
| +//
|
| +// WHY NOT GOOGLE CALLBACKS?
|
| +//
|
| +// The Google callback system also does not support refcounting. Furthermore,
|
| +// its implementation has a number of strange edge cases with respect to type
|
| +// conversion of its arguments. In particular, the argument's constness must
|
| +// at times match exactly the function signature, or the type-inference might
|
| +// break. Given the above, writing a custom solution was easier.
|
| +//
|
| +//
|
| +// MISSING FUNCTIONALITY
|
| +// - Invoking the return of Bind. Bind(&foo).Run() does not work;
|
| +// - Binding arrays to functions that take a non-const pointer.
|
| +// Example:
|
| +// void Foo(const char* ptr);
|
| +// void Bar(char* ptr);
|
| +// Bind(&Foo, "test");
|
| +// Bind(&Bar, "test"); // This fails because ptr is not const.
|
| +
|
| +namespace base {
|
| +
|
| +// First, we forward declare the Callback class template. This informs the
|
| +// compiler that the template only has 1 type parameter which is the function
|
| +// signature that the Callback is representing.
|
| +//
|
| +// After this, create template specializations for 0-6 parameters. Note that
|
| +// even though the template typelist grows, the specialization still
|
| +// only has one type: the function signature.
|
| +template <typename Sig>
|
| +class Callback;
|
| +
|
| +template <typename R>
|
| +class Callback<R(void)> {
|
| public:
|
| - typedef Params TupleType;
|
| -
|
| - virtual ~CallbackRunner() {}
|
| - virtual void RunWithParams(const Params& params) = 0;
|
| -
|
| - // Convenience functions so callers don't have to deal with Tuples.
|
| - inline void Run() {
|
| - RunWithParams(Tuple0());
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| }
|
|
|
| - template <typename Arg1>
|
| - inline void Run(const Arg1& a) {
|
| - RunWithParams(Params(a));
|
| + R Run(void) const {
|
| + return polymorphic_invoke_(invoker_storage_.get());
|
| }
|
|
|
| - template <typename Arg1, typename Arg2>
|
| - inline void Run(const Arg1& a, const Arg2& b) {
|
| - RunWithParams(Params(a, b));
|
| - }
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
|
|
| - template <typename Arg1, typename Arg2, typename Arg3>
|
| - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
|
| - RunWithParams(Params(a, b, c));
|
| +template <typename R, typename A1>
|
| +class Callback<R(A1)> {
|
| + public:
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| }
|
|
|
| - template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
| - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
|
| - RunWithParams(Params(a, b, c, d));
|
| + R Run(const A1& a1) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1);
|
| }
|
|
|
| - template <typename Arg1, typename Arg2, typename Arg3,
|
| - typename Arg4, typename Arg5>
|
| - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
|
| - const Arg4& d, const Arg5& e) {
|
| - RunWithParams(Params(a, b, c, d, e));
|
| - }
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T, typename Method, typename Params>
|
| -class CallbackImpl : public CallbackStorage<T, Method>,
|
| - public CallbackRunner<Params> {
|
| +template <typename R, typename A1, typename A2>
|
| +class Callback<R(A1, A2)> {
|
| public:
|
| - CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| }
|
| - virtual void RunWithParams(const Params& params) {
|
| - // use "this->" to force C++ to look inside our templatized base class; see
|
| - // Effective C++, 3rd Ed, item 43, p210 for details.
|
| - DispatchToMethod(this->obj_, this->meth_, params);
|
| +
|
| + R Run(const A1& a1,
|
| + const A2& a2) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1,
|
| + a2);
|
| }
|
| -};
|
|
|
| -// 0-arg implementation
|
| -struct Callback0 {
|
| - typedef CallbackRunner<Tuple0> Type;
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T>
|
| -typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
|
| - return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
|
| -}
|
| -
|
| -// 1-arg implementation
|
| -template <typename Arg1>
|
| -struct Callback1 {
|
| - typedef CallbackRunner<Tuple1<Arg1> > Type;
|
| -};
|
| +template <typename R, typename A1, typename A2, typename A3>
|
| +class Callback<R(A1, A2, A3)> {
|
| + public:
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&,
|
| + const A3&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
|
|
| -template <class T, typename Arg1>
|
| -typename Callback1<Arg1>::Type* NewCallback(T* object,
|
| - void (T::*method)(Arg1)) {
|
| - return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
|
| -}
|
| + R Run(const A1& a1,
|
| + const A2& a2,
|
| + const A3& a3) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1,
|
| + a2,
|
| + a3);
|
| + }
|
|
|
| -// 2-arg implementation
|
| -template <typename Arg1, typename Arg2>
|
| -struct Callback2 {
|
| - typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T, typename Arg1, typename Arg2>
|
| -typename Callback2<Arg1, Arg2>::Type* NewCallback(
|
| - T* object,
|
| - void (T::*method)(Arg1, Arg2)) {
|
| - return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
|
| - Tuple2<Arg1, Arg2> >(object, method);
|
| -}
|
| -
|
| -// 3-arg implementation
|
| -template <typename Arg1, typename Arg2, typename Arg3>
|
| -struct Callback3 {
|
| - typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
|
| -};
|
| +template <typename R, typename A1, typename A2, typename A3, typename A4>
|
| +class Callback<R(A1, A2, A3, A4)> {
|
| + public:
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&,
|
| + const A3&,
|
| + const A4&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
|
|
| -template <class T, typename Arg1, typename Arg2, typename Arg3>
|
| -typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
|
| - T* object,
|
| - void (T::*method)(Arg1, Arg2, Arg3)) {
|
| - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3),
|
| - Tuple3<Arg1, Arg2, Arg3> >(object, method);
|
| -}
|
| -
|
| -// 4-arg implementation
|
| -template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
| -struct Callback4 {
|
| - typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
|
| -};
|
| + R Run(const A1& a1,
|
| + const A2& a2,
|
| + const A3& a3,
|
| + const A4& a4) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1,
|
| + a2,
|
| + a3,
|
| + a4);
|
| + }
|
|
|
| -template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
| -typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
|
| - T* object,
|
| - void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
|
| - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
|
| - Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
|
| -}
|
| -
|
| -// 5-arg implementation
|
| -template <typename Arg1, typename Arg2, typename Arg3,
|
| - typename Arg4, typename Arg5>
|
| -struct Callback5 {
|
| - typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T, typename Arg1, typename Arg2,
|
| - typename Arg3, typename Arg4, typename Arg5>
|
| -typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
|
| - T* object,
|
| - void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
|
| - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
|
| - Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
|
| -}
|
| -
|
| -// An UnboundMethod is a wrapper for a method where the actual object is
|
| -// provided at Run dispatch time.
|
| -template <class T, class Method, class Params>
|
| -class UnboundMethod {
|
| +template <typename R, typename A1, typename A2, typename A3, typename A4,
|
| + typename A5>
|
| +class Callback<R(A1, A2, A3, A4, A5)> {
|
| public:
|
| - UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
|
| - COMPILE_ASSERT(
|
| - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
|
| - badunboundmethodparams);
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&,
|
| + const A3&,
|
| + const A4&,
|
| + const A5&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| }
|
| - void Run(T* obj) const {
|
| - DispatchToMethod(obj, m_, p_);
|
| +
|
| + R Run(const A1& a1,
|
| + const A2& a2,
|
| + const A3& a3,
|
| + const A4& a4,
|
| + const A5& a5) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1,
|
| + a2,
|
| + a3,
|
| + a4,
|
| + a5);
|
| }
|
| - private:
|
| - Method m_;
|
| - Params p_;
|
| -};
|
|
|
| -// Return value implementation with no args.
|
| -template <typename ReturnValue>
|
| -struct CallbackWithReturnValue {
|
| - class Type {
|
| - public:
|
| - virtual ~Type() {}
|
| - virtual ReturnValue Run() = 0;
|
| - };
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T, typename Method, typename ReturnValue>
|
| -class CallbackWithReturnValueImpl
|
| - : public CallbackStorage<T, Method>,
|
| - public CallbackWithReturnValue<ReturnValue>::Type {
|
| +template <typename R, typename A1, typename A2, typename A3, typename A4,
|
| + typename A5, typename A6>
|
| +class Callback<R(A1, A2, A3, A4, A5, A6)> {
|
| public:
|
| - CallbackWithReturnValueImpl(T* obj, Method meth)
|
| - : CallbackStorage<T, Method>(obj, meth) {}
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&,
|
| + const A3&,
|
| + const A4&,
|
| + const A5&,
|
| + const A6&);
|
| +
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + // We pass InvokerStorageHolder by const ref to avoid incurring an
|
| + // unnecessary AddRef/Unref pair even though we will modify the object.
|
| + // We cannot use a normal reference because the compiler will warn
|
| + // since this is often used on a return value, which is a temporary.
|
| + //
|
| + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
| + // return the exact Callback<> type. See base/bind.h for details.
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
|
|
| - virtual ReturnValue Run() {
|
| - return (this->obj_->*(this->meth_))();
|
| + R Run(const A1& a1,
|
| + const A2& a2,
|
| + const A3& a3,
|
| + const A4& a4,
|
| + const A5& a5,
|
| + const A6& a6) const {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1,
|
| + a2,
|
| + a3,
|
| + a4,
|
| + a5,
|
| + a6);
|
| }
|
|
|
| - protected:
|
| - virtual ~CallbackWithReturnValueImpl() {}
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| };
|
|
|
| -template <class T, typename ReturnValue>
|
| -typename CallbackWithReturnValue<ReturnValue>::Type*
|
| -NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) {
|
| - return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>(
|
| - object, method);
|
| -}
|
| +
|
| +// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
|
| +// will be used in a lot of APIs with delayed execution.
|
| +typedef Callback<void(void)> Closure;
|
| +
|
| +} // namespace base
|
|
|
| #endif // BASE_CALLBACK_H
|
|
|