| Index: base/uber_callback.h
|
| diff --git a/base/uber_callback.h b/base/uber_callback.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37c0078b7610929832d4669a7cca828721f1a5f6
|
| --- /dev/null
|
| +++ b/base/uber_callback.h
|
| @@ -0,0 +1,291 @@
|
| +// This file was GENERATED by command:
|
| +// pump.py uber_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.
|
| +
|
| +#ifndef BASE_UBER_CALLBACK_H_
|
| +#define BASE_UBER_CALLBACK_H_
|
| +#pragma once
|
| +
|
| +#include "base/uber_callback_helpers.h"
|
| +
|
| +// 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 funciton object. Together
|
| +// with the Prebind() function in prebind.h, they provide a type-safe method
|
| +// for performing currying of arguments, and createing 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.
|
| +//
|
| +// EXAMPLE USAGE:
|
| +//
|
| +// /* Binding a class member. */
|
| +// class Ref : public RefCountedThreadSafe<Ref> {
|
| +// int Foo() { return 3; }
|
| +// };
|
| +// scoped_refptr<Ref> ref = new Ref();
|
| +// Callback<int(void)> ref_cb = Prebind(&Ref::Foo, ref.get());
|
| +// LOG(INFO) << ref_cb.Run(); // Prints out 3.
|
| +//
|
| +// /* Binding a class member for a non-refcounted class. */
|
| +// class NoRef {
|
| +// int Foo() { return 4; }
|
| +// };
|
| +// NoRef no_ref;
|
| +// Callback<int(void)> no_ref_cb = Prebind(&NoRef::Foo, Unretained(&no_ref));
|
| +// LOG(INFO) << ref_cb.Run(); // Prints out 4.
|
| +//
|
| +// /* Binding a normal function. */
|
| +// int Return5() { return 5; }
|
| +// Callback<int(int)> func_cb = Prebind(&Return5);
|
| +// LOG(INFO) << func_cb.Run(5); // Prints 5.
|
| +//
|
| +// /* Binding a reference. */
|
| +// int Identity(int n) { return n; }
|
| +// int value = 1;
|
| +// Callback<int(void)> bound_copy_cb = Prebind(&Identity, value);
|
| +// Callback<int(void)> bound_ref_cb = Prebind(&Identity, 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 Prebind is heavily influenced by C++'s
|
| +// tr1::function/tr1::bind, and by the "Google Callback" system used inside
|
| +// Google.
|
| +//
|
| +//
|
| +// 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 convertable 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.
|
| +
|
| +namespace base {
|
| +
|
| +// First, we forward declare the Callback class template. This informs the
|
| +// compiler that ther template only have 1 type parameter: the function
|
| +// signature that the Callback is abstracting.
|
| +//
|
| +// After this, create template specializations for 0-6 parameters. Note that
|
| +// even though the template typelist grows, that the specialization still
|
| +// only has one type: the function signature.
|
| +//
|
| +// Also, note that the templated constructor should *not* be explicit. This is
|
| +// to allow the natural assignment syntax from the result of Prebind(), which
|
| +// is not the same type as Callback(). See the description of Prebind for
|
| +// details.
|
| +template <typename Sig>
|
| +class Callback;
|
| +
|
| +template <typename R>
|
| +class Callback<R(void)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(void) {
|
| + return polymorphic_invoke_(invoker_storage_.get());
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +template <typename R, typename A1>
|
| +class Callback<R(A1)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +template <typename R, typename A1, typename A2>
|
| +class Callback<R(A1, A2)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1, const A2& a2) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1, a2);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +template <typename R, typename A1, typename A2, typename A3>
|
| +class Callback<R(A1, A2, A3)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&, const A3&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1, const A2& a2, const A3& a3) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +template <typename R, typename A1, typename A2, typename A3, typename A4>
|
| +class Callback<R(A1, A2, A3, A4)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&, const A3&, const A4&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +template <typename R, typename A1, typename A2, typename A3, typename A4,
|
| + typename A5>
|
| +class Callback<R(A1, A2, A3, A4, A5)> {
|
| + public:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&, const A3&, const A4&, const A5&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +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:
|
| + Callback() : polymorphic_invoke_(NULL) { }
|
| +
|
| + typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
|
| + const A2&, const A3&, const A4&, const A5&, const A6&);
|
| +
|
| + template <typename T>
|
| + Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
|
| + : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
|
| + invoker_storage_.swap(invoker_holder.invoker_storage_);
|
| + }
|
| +
|
| + R Run(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5,
|
| + const A6& a6) {
|
| + return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5, a6);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
|
| + PolymorphicInvoke polymorphic_invoke_;
|
| +};
|
| +
|
| +
|
| +// Syntactic sugar to make Callbacks<void(void)> easier to read since it will
|
| +// be used in a lot of APIs with delayed execution.
|
| +typedef Callback<void(void)> Closure;
|
| +
|
| +} // namespace base
|
| +
|
| +#endif // BASE_UBER_CALLBACK_H
|
|
|