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

Side by Side Diff: docs/callback.md

Issue 2300983004: Move documentation of base::Callback from base/callback.h to docs/callback.md (Closed)
Patch Set: fix indentations. use codeblock for code snippets. Created 4 years, 3 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
« no previous file with comments | « base/callback.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1
2 # Introduction
3
4 The templated Callback class is a generalized function object. Together
5 with the `Bind()` function in bind.h, they provide a type-safe method for
6 performing partial application of functions.
7
8 Partial application (or "currying") is the process of binding a subset of
9 a function's arguments to produce another function that takes fewer
10 arguments. This can be used to pass around a unit of delayed execution,
11 much like lexical closures are used in other languages. For example, it
12 is used in Chromium code to schedule tasks on different MessageLoops.
13
14 A callback with no unbound input parameters (`base::Callback<void()>`)
15 is called a `base::Closure`. Note that this is NOT the same as what other
16 languages refer to as a closure -- it does not retain a reference to its
17 enclosing environment.
18
19 ## MEMORY MANAGEMENT AND PASSING
20
21 The Callback objects themselves should be passed by const-reference, and
22 stored by copy. They internally store their state via a refcounted class
23 and thus do not need to be deleted.
24
25 The reason to pass via a const-reference is to avoid unnecessary
26 AddRef/Release pairs to the internal state.
27
28
29 # Quick reference for basic stuff
30
31 ## BINDING A BARE FUNCTION
32
33 ```cpp
34 int Return5() { return 5; }
35 base::Callback<int()> func_cb = base::Bind(&Return5);
36 LOG(INFO) << func_cb.Run(); // Prints 5.
37 ```
38
39 ## BINDING A CLASS METHOD
40
41 The first argument to bind is the member function to call, the second is
42 the object on which to call it.
43
44 ```cpp
45 class Ref : public base::RefCountedThreadSafe<Ref> {
46 public:
47 int Foo() { return 3; }
48 void PrintBye() { LOG(INFO) << "bye."; }
49 };
50 scoped_refptr<Ref> ref = new Ref();
51 base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref);
52 LOG(INFO) << ref_cb.Run(); // Prints out 3.
53 ```
54
55 By default the object must support RefCounted or you will get a compiler
56 error. If you're passing between threads, be sure it's
57 RefCountedThreadSafe! See "Advanced binding of member functions" below if
58 you don't want to use reference counting.
59
60 ## RUNNING A CALLBACK
61
62 Callbacks can be run with their `Run` method, which has the same
63 signature as the template argument to the callback.
64
65 ```cpp
66 void DoSomething(const base::Callback<void(int, std::string)>& callback) {
67 callback.Run(5, "hello");
68 }
69 ```
70
71 Callbacks can be run more than once (they don't get deleted or marked when
72 run). However, this precludes using base::Passed (see below).
73
74 ```cpp
75 void DoSomething(const base::Callback<double(double)>& callback) {
76 double myresult = callback.Run(3.14159);
77 myresult += callback.Run(2.71828);
78 }
79 ```
80
81 ## PASSING UNBOUND INPUT PARAMETERS
82
83 Unbound parameters are specified at the time a callback is `Run()`. They are
84 specified in the `Callback` template type:
85
86 ```cpp
87 void MyFunc(int i, const std::string& str) {}
88 base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc);
89 cb.Run(23, "hello, world");
90 ```
91
92 ## PASSING BOUND INPUT PARAMETERS
93
94 Bound parameters are specified when you create the callback as arguments
95 to `Bind()`. They will be passed to the function and the `Run()`ner of the
96 callback doesn't see those values or even know that the function it's
97 calling.
98
99 ```cpp
100 void MyFunc(int i, const std::string& str) {}
101 base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world");
102 cb.Run();
103 ```
104
105 A callback with no unbound input parameters (`base::Callback<void()>`)
106 is called a `base::Closure`. So we could have also written:
107
108 ```cpp
109 base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
110 ```
111
112 When calling member functions, bound parameters just go after the object
113 pointer.
114
115 ```cpp
116 base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
117 ```
118
119 ## PARTIAL BINDING OF PARAMETERS
120
121 You can specify some parameters when you create the callback, and specify
122 the rest when you execute the callback.
123
124 ```cpp
125 void MyFunc(int i, const std::string& str) {}
126 base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23);
127 cb.Run("hello world");
128 ```
129
130 When calling a function bound parameters are first, followed by unbound
131 parameters.
132
133
134 # Quick reference for advanced binding
135
136 ## BINDING A CLASS METHOD WITH WEAK POINTERS
137
138 ```cpp
139 base::Bind(&MyClass::Foo, GetWeakPtr());
140 ``
141
142 The callback will not be run if the object has already been destroyed.
143 DANGER: weak pointers are not threadsafe, so don't use this
144 when passing between threads!
145
146 ## BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT
147
148 ```cpp
149 base::Bind(&MyClass::Foo, base::Unretained(this));
150 ```
151
152 This disables all lifetime management on the object. You're responsible
153 for making sure the object is alive at the time of the call. You break it,
154 you own it!
155
156 ## BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS
157
158 ```cpp
159 MyClass* myclass = new MyClass;
160 base::Bind(&MyClass::Foo, base::Owned(myclass));
161 ```
162
163 The object will be deleted when the callback is destroyed, even if it's
164 not run (like if you post a task during shutdown). Potentially useful for
165 "fire and forget" cases.
166
167 ## IGNORING RETURN VALUES
168
169 Sometimes you want to call a function that returns a value in a callback
170 that doesn't expect a return value.
171
172 ```cpp
173 int DoSomething(int arg) { cout << arg << endl; }
174 base::Callback<void(int)> cb =
175 base::Bind(base::IgnoreResult(&DoSomething));
176 ```
177
178 # Quick reference for binding parameters to Bind()
179
180 Bound parameters are specified as arguments to `Bind()` and are passed to the
181 function. A callback with no parameters or no unbound parameters is called a
182 `Closure` (`base::Callback<void()>` and `base::Closure` are the same thing).
183
184 ## PASSING PARAMETERS OWNED BY THE CALLBACK
185
186 ```cpp
187 void Foo(int* arg) { cout << *arg << endl; }
188 int* pn = new int(1);
189 base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
190 ```
191
192 The parameter will be deleted when the callback is destroyed, even if it's
193 not run (like if you post a task during shutdown).
194
195 ## PASSING PARAMETERS AS A scoped_ptr
196
197 ```cpp
198 void TakesOwnership(std::unique_ptr<Foo> arg) {}
199 std::unique_ptr<Foo> f(new Foo);
200 // f becomes null during the following call.
201 base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
202 ```
203
204 Ownership of the parameter will be with the callback until the callback is
205 run, and then ownership is passed to the callback function. This means the
206 callback can only be run once. If the callback is never run, it will delete
207 the object when it's destroyed.
208
209 ## PASSING PARAMETERS AS A scoped_refptr
210
211 ```cpp
212 void TakesOneRef(scoped_refptr<Foo> arg) {}
213 scoped_refptr<Foo> f(new Foo)
214 base::Closure cb = base::Bind(&TakesOneRef, f);
215 ```
216
217 This should "just work." The closure will take a reference as long as it
218 is alive, and another reference will be taken for the called function.
219
220 ## PASSING PARAMETERS BY REFERENCE
221
222 Const references are *copied* unless `ConstRef` is used. Example:
223
224 ```cpp
225 void foo(const int& arg) { printf("%d %p\n", arg, &arg); }
226 int n = 1;
227 base::Closure has_copy = base::Bind(&foo, n);
228 base::Closure has_ref = base::Bind(&foo, base::ConstRef(n));
229 n = 2;
230 foo(n); // Prints "2 0xaaaaaaaaaaaa"
231 has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb"
232 has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa"
233 ```
234
235 Normally parameters are copied in the closure. DANGER: ConstRef stores a
236 const reference instead, referencing the original parameter. This means
237 that you must ensure the object outlives the callback!
238
239
240 # Implementation notes
241
242 ## WHERE IS THIS DESIGN FROM:
243
244 The design `Callback` and Bind is heavily influenced by C++'s
245 `tr1::function`/`tr1::bind`, and by the "Google Callback" system used inside
246 Google.
247
248 ## HOW THE IMPLEMENTATION WORKS:
249
250 There are three main components to the system:
251 1) The Callback classes.
252 2) The `Bind()` functions.
253 3) The arguments wrappers (e.g., `Unretained()` and `ConstRef()`).
254
255 The Callback classes represent a generic function pointer. Internally,
256 it stores a refcounted piece of state that represents the target function
257 and all its bound parameters. Each `Callback` specialization has a templated
258 constructor that takes an `BindState<>*`. In the context of the constructor,
259 the static type of this `BindState<>` pointer uniquely identifies the
260 function it is representing, all its bound parameters, and a `Run()` method
261 that is capable of invoking the target.
262
263 `Callback`'s constructor takes the `BindState<>*` that has the full static type
264 and erases the target function type as well as the types of the bound
265 parameters. It does this by storing a pointer to the specific `Run()`
266 function, and upcasting the state of `BindState<>*` to a
267 `BindStateBase*`. This is safe as long as this `BindStateBase` pointer
268 is only used with the stored `Run()` pointer.
269
270 To `BindState<>` objects are created inside the `Bind()` functions.
271 These functions, along with a set of internal templates, are responsible for
272
273 - Unwrapping the function signature into return type, and parameters
274 - Determining the number of parameters that are bound
275 - Creating the BindState storing the bound parameters
276 - Performing compile-time asserts to avoid error-prone behavior
277 - Returning an `Callback<>` with an arity matching the number of unbound
278 parameters and that knows the correct refcounting semantics for the
279 target object if we are binding a method.
280
281 The `Bind` functions do the above using type-inference, and template
282 specializations.
283
284 By default `Bind()` will store copies of all bound parameters, and attempt
285 to refcount a target object if the function being bound is a class method.
286 These copies are created even if the function takes parameters as const
287 references. (Binding to non-const references is forbidden, see bind.h.)
288
289 To change this behavior, we introduce a set of argument wrappers
290 (e.g., `Unretained()`, and `ConstRef()`). These are simple container templates
291 that are passed by value, and wrap a pointer to argument. See the
292 file-level comment in base/bind_helpers.h for more info.
293
294 These types are passed to the `Unwrap()` functions, and the `MaybeRefcount()`
295 functions respectively to modify the behavior of `Bind()`. The `Unwrap()`
296 and `MaybeRefcount()` functions change behavior by doing partial
297 specialization based on whether or not a parameter is a wrapper type.
298
299 `ConstRef()` is similar to `tr1::cref`. `Unretained()` is specific to Chromium.
300
301
302 ## WHY NOT TR1 FUNCTION/BIND?
303
304 Direct use of `tr1::function` and `tr1::bind` was considered, but ultimately
305 rejected because of the number of copy constructors invocations involved
306 in the binding of arguments during construction, and the forwarding of
307 arguments during invocation. These copies will no longer be an issue in
308 C++0x because C++0x will support rvalue reference allowing for the compiler
309 to avoid these copies. However, waiting for C++0x is not an option.
310
311 Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
312 `tr1::bind` call itself will invoke a non-trivial copy constructor three times
313 for each bound parameter. Also, each when passing a `tr1::function`, each
314 bound argument will be copied again.
315
316 In addition to the copies taken at binding and invocation, copying a
317 `tr1::function` causes a copy to be made of all the bound parameters and
318 state.
319
320 Furthermore, in Chromium, it is desirable for the `Callback` to take a
321 reference on a target object when representing a class method call. This
322 is not supported by tr1.
323
324 Lastly, `tr1::function` and `tr1::bind` has a more general and flexible API.
325 This includes things like argument reordering by use of
326 `tr1::bind::placeholder`, support for non-const reference parameters, and some
327 limited amount of subtyping of the `tr1::function` object (e.g.,
328 `tr1::function<int(int)>` is convertible to `tr1::function<void(int)>`).
329
330 These are not features that are required in Chromium. Some of them, such as
331 allowing for reference parameters, and subtyping of functions, may actually
332 become a source of errors. Removing support for these features actually
333 allows for a simpler implementation, and a terser Currying API.
334
335 ## WHY NOT GOOGLE CALLBACKS?
336
337 The Google callback system also does not support refcounting. Furthermore,
338 its implementation has a number of strange edge cases with respect to type
339 conversion of its arguments. In particular, the argument's constness must
340 at times match exactly the function signature, or the type-inference might
341 break. Given the above, writing a custom solution was easier.
342
343
344 ## MISSING FUNCTIONALITY
345 - Invoking the return of `Bind`. `Bind(&foo).Run()` does not work;
346 - Binding arrays to functions that take a non-const pointer.
347 Example:
348 ```cpp
349 void Foo(const char* ptr);
350 void Bar(char* ptr);
351 Bind(&Foo, "test");
352 Bind(&Bar, "test"); // This fails because ptr is not const.
353 ```
354
355 If you are thinking of forward declaring `Callback` in your own header file,
356 please include "base/callback_forward.h" instead.
OLDNEW
« no previous file with comments | « base/callback.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698