Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: base/callback.h.pump

Issue 6109007: Unified callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: Address Will's comments. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/callback.h ('k') | base/callback_helpers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 $$ This is a pump file for generating file templates. Pump is a python
2 $$ script that is part of the Google Test suite of utilities. Description
3 $$ can be found here:
4 $$
5 $$ http://code.google.com/p/googletest/wiki/PumpManual
6 $$
7
8 $var MAX_ARITY = 6
9
10 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
11 // Use of this source code is governed by a BSD-style license that can be
12 // found in the LICENSE file.
13
14 #ifndef BASE_CALLBACK_H_
15 #define BASE_CALLBACK_H_
16 #pragma once
17
18 #include "base/callback_helpers.h"
19 #include "base/callback_old.h"
20
21 // New, super-duper, unified Callback system. This will eventually replace
22 // NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
23 // systems currently in the Chromium code base.
24 //
25 // WHAT IS THIS:
26 //
27 // The templated Callback class is a generalized function object. Together
28 // with the Bind() function in bind.h, they provide a type-safe method for
29 // performing currying of arguments, and creating a "closure."
30 //
31 // In programing languages, a closure is a first-class function where all its
32 // parameters have been bound (usually via currying). Closures are well
33 // suited for representing, and passing around a unit of delayed execution.
34 // They are used in Chromium code to schedule tasks on different MessageLoops.
35 //
36 //
37 // MEMORY MANAGEMENT AND PASSING
38 //
39 // The Callback objects themselves should be passed by const-reference, and
40 // stored by copy. They internally store their state via a refcounted class
41 // and thus do not need to be deleted.
42 //
43 // The reason to pass via a const-reference is to avoid unnecessary
44 // AddRef/Release pairs to the internal state.
45 //
46 //
47 // EXAMPLE USAGE:
48 //
49 // /* Binding a normal function. */
50 // int Return5() { return 5; }
51 // base::Callback<int(int)> func_cb = base::Bind(&Return5);
52 // LOG(INFO) << func_cb.Run(5); // Prints 5.
53 //
54 // void PrintHi() { LOG(INFO) << "hi."; }
55 // base::Closure void_func_cb = base::Bind(&PrintHi);
56 // LOG(INFO) << void_func_cb.Run(); // Prints: hi.
57 //
58 // /* Binding a class method. */
59 // class Ref : public RefCountedThreadSafe<Ref> {
60 // public:
61 // int Foo() { return 3; }
62 // void PrintBye() { LOG(INFO) << "bye."; }
63 // };
64 // scoped_refptr<Ref> ref = new Ref();
65 // base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
66 // LOG(INFO) << ref_cb.Run(); // Prints out 3.
67 //
68 // base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
69 // void_ref_cb.Run(); // Prints: bye.
70 //
71 // /* Binding a class method in a non-refcounted class.
72 // *
73 // * WARNING: You must be sure the referee outlives the callback!
74 // * This is particularly important if you post a closure to a
75 // * MessageLoop because then it becomes hard to know what the
76 // * lifetime of the referee needs to be.
77 // */
78 // class NoRef {
79 // public:
80 // int Foo() { return 4; }
81 // void PrintWhy() { LOG(INFO) << "why???"; }
82 // };
83 // NoRef no_ref;
84 // base::Callback<int(void)> base::no_ref_cb =
85 // base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
86 // LOG(INFO) << ref_cb.Run(); // Prints out 4.
87 //
88 // base::Closure void_no_ref_cb =
89 // base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
90 // void_no_ref_cb.Run(); // Prints: why???
91 //
92 // /* Binding a reference. */
93 // int Identity(int n) { return n; }
94 // int value = 1;
95 // base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
96 // base::Callback<int(void)> bound_ref_cb =
97 // base::Bind(&Identity, base::ConstRef(value));
98 // LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
99 // LOG(INFO) << bound_ref_cb.Run(); // Prints 1.
100 // value = 2;
101 // LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
102 // LOG(INFO) << bound_ref_cb.Run(); // Prints 2.
103 //
104 //
105 // WHERE IS THIS DESIGN FROM:
106 //
107 // The design Callback and Bind is heavily influenced by C++'s
108 // tr1::function/tr1::bind, and by the "Google Callback" system used inside
109 // Google.
110 //
111 //
112 // HOW THE IMPLEMENTATION WORKS:
113 //
114 // There are three main components to the system:
115 // 1) The Callback classes.
116 // 2) The Bind() functions.
117 // 3) The arguments wrappers (eg., Unretained() and ConstRef()).
118 //
119 // The Callback classes represent a generic function pointer. Internally,
120 // it stores a refcounted piece of state that represents the target function
121 // and all its bound parameters. Each Callback specialization has a templated
122 // constructor that takes an InvokerStorageHolder<> object. In the context of
123 // the constructor, the static type of this InvokerStorageHolder<> object
124 // uniquely identifies the function it is representing, all its bound
125 // parameters, and a DoInvoke() that is capable of invoking the target.
126 //
127 // Callback's constructor is takes the InvokerStorageHolder<> that has the
128 // full static type and erases the target function type, and the bound
129 // parameters. It does this by storing a pointer to the specific DoInvoke()
130 // function, and upcasting the state of InvokerStorageHolder<> to a
131 // InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
132 // is only used with the stored DoInvoke() pointer.
133 //
134 // To create InvokerStorageHolder<> objects, we use the Bind() functions.
135 // These functions, along with a set of internal templates, are reponsible for
136 //
137 // - Unwrapping the function signature into return type, and parameters
138 // - Determining the number of parameters that are bound
139 // - Creating the storage for the bound parameters
140 // - Performing compile-time asserts to avoid error-prone behavior
141 // - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity
142 // matching the number of unbound parameters, and knows the correct
143 // refcounting semantics for the target object if we are binding a class
144 // method.
145 //
146 // The Bind functions do the above using type-inference, and template
147 // specializations.
148 //
149 // By default Bind() will store copies of all bound parameters, and attempt
150 // to refcount a target object if the function being bound is a class method.
151 //
152 // To change this behavior, we introduce a set of argument wrappers
153 // (eg. Unretained(), and ConstRef()). These are simple container templates
154 // that are passed by value, and wrap a pointer to argument. See the
155 // file-level comment in base/bind_helpers.h for more info.
156 //
157 // These types are passed to the Unwrap() functions, and the MaybeRefcount()
158 // functions respectively to modify the behavior of Bind(). The Unwrap()
159 // and MaybeRefcount() functions change behavior by doing partial
160 // specialization based on whether or not a parameter is a wrapper type.
161 //
162 // ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium.
163 //
164 //
165 // WHY NOT TR1 FUNCTION/BIND?
166 //
167 // Direct use of tr1::function and tr1::bind was considered, but ultimately
168 // rejected because of the number of copy constructors invocations involved
169 // in the binding of arguments during construction, and the forwarding of
170 // arguments during invocation. These copies will no longer be an issue in
171 // C++0x because C++0x will support rvalue reference allowing for the compiler
172 // to avoid these copies. However, waiting for C++0x is not an option.
173 //
174 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
175 // tr1::bind call itself will invoke a non-trivial copy constructor three times
176 // for each bound parameter. Also, each when passing a tr1::function, each
177 // bound argument will be copied again.
178 //
179 // In addition to the copies taken at binding and invocation, copying a
180 // tr1::function causes a copy to be made of all the bound parameters and
181 // state.
182 //
183 // Furthermore, in Chromium, it is desirable for the Callback to take a
184 // reference on a target object when representing a class method call. This
185 // is not supported by tr1.
186 //
187 // Lastly, tr1::function and tr1::bind has a more general and flexible API.
188 // This includes things like argument reordering by use of
189 // tr1::bind::placeholder, support for non-const reference parameters, and some
190 // limited amount of subtyping of the tr1::function object (eg.,
191 // tr1::function<int(int)> is convertible to tr1::function<void(int)>).
192 //
193 // These are not features that are required in Chromium. Some of them, such as
194 // allowing for reference parameters, and subtyping of functions, may actually
195 // because a source of errors. Removing support for these features actually
196 // allows for a simpler implementation, and a terser Currying API.
197 //
198 //
199 // WHY NOT GOOGLE CALLBACKS?
200 //
201 // The Google callback system also does not support refcounting. Furthermore,
202 // its implementation has a number of strange edge cases with respect to type
203 // conversion of its arguments. In particular, the argument's constness must
204 // at times match exactly the function signature, or the type-inference might
205 // break. Given the above, writing a custom solution was easier.
206 //
207 //
208 // MISSING FUNCTIONALITY
209 // - Invoking the return of Bind. Bind(&foo).Run() does not work;
210 // - Binding arrays to functions that take a non-const pointer.
211 // Example:
212 // void Foo(const char* ptr);
213 // void Bar(char* ptr);
214 // Bind(&Foo, "test");
215 // Bind(&Bar, "test"); // This fails because ptr is not const.
216
217 namespace base {
218
219 // First, we forward declare the Callback class template. This informs the
220 // compiler that the template only has 1 type parameter which is the function
221 // signature that the Callback is representing.
222 //
223 // After this, create template specializations for 0-$(MAX_ARITY) parameters. No te that
224 // even though the template typelist grows, the specialization still
225 // only has one type: the function signature.
226 template <typename Sig>
227 class Callback;
228
229
230 $range ARITY 0..MAX_ARITY
231 $for ARITY [[
232 $range ARG 1..ARITY
233
234 $if ARITY == 0 [[
235 template <typename R>
236 class Callback<R(void)> {
237 ]] $else [[
238 template <typename R, $for ARG , [[typename A$(ARG)]]>
239 class Callback<R($for ARG , [[A$(ARG)]])> {
240 ]]
241
242 public:
243 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*[[]]
244 $if ARITY != 0 [[, ]]
245 $for ARG ,
246 [[const A$(ARG)&]]);
247
248 Callback() : polymorphic_invoke_(NULL) { }
249
250 // We pass InvokerStorageHolder by const ref to avoid incurring an
251 // unnecessary AddRef/Unref pair even though we will modify the object.
252 // We cannot use a normal reference because the compiler will warn
253 // since this is often used on a return value, which is a temporary.
254 //
255 // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
256 // return the exact Callback<> type. See base/bind.h for details.
257 template <typename T>
258 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
259 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
260 invoker_storage_.swap(invoker_holder.invoker_storage_);
261 }
262
263
264 $if ARITY == 0 [[
265 R Run(void) const {
266 ]] $else [[
267 R Run($for ARG ,
268 [[const A$(ARG)& a$(ARG)]]) const {
269 ]]
270
271 return polymorphic_invoke_(invoker_storage_.get()[[]]
272 $if ARITY != 0 [[, ]]
273 $for ARG ,
274 [[a$(ARG)]]);
275 }
276
277 private:
278 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
279 PolymorphicInvoke polymorphic_invoke_;
280 };
281
282
283 ]] $$ for ARITY
284
285 // Syntactic sugar to make Callbacks<void(void)> easier to declare since it
286 // will be used in a lot of APIs with delayed execution.
287 typedef Callback<void(void)> Closure;
288
289 } // namespace base
290
291 #endif // BASE_CALLBACK_H
OLDNEW
« no previous file with comments | « base/callback.h ('k') | base/callback_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698