diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-15 01:27:38 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-15 01:27:38 +0000 |
commit | b38d3578e53d0a7f441c6858334a2d9f08e5c024 (patch) | |
tree | 917a1d893c40fd10408e172b1a66cba692a0fedc /base/callback.h | |
parent | c41fe6697e38057138cbe33332d9882e0d7d9b4b (diff) | |
download | chromium_src-b38d3578e53d0a7f441c6858334a2d9f08e5c024.zip chromium_src-b38d3578e53d0a7f441c6858334a2d9f08e5c024.tar.gz chromium_src-b38d3578e53d0a7f441c6858334a2d9f08e5c024.tar.bz2 |
Unified callback system based on tr1::function/tr1::bind and Google's internal callback code.
This callback system allows for creation of functors for normal functions, methods, and const methods. It is a superset of the functionality of NewRunnableMethod, NewRunnableFunction, NewCallback, and CreateFunctor.
We support partial binding of function arguments, and also specification of refcounting semantics by wrapping a target object in a wrapper object.
BUG=35223
TEST=none
Review URL: http://codereview.chromium.org/6109007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74904 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/callback.h')
-rw-r--r-- | base/callback.h | 640 |
1 files changed, 434 insertions, 206 deletions
diff --git a/base/callback.h b/base/callback.h index e5ea771..05a7182 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 |