Fix docs/callback.md style
* Add document title * Fix line wrapping Review-Url: https://codereview.chromium.org/2314463002 Cr-Commit-Position: refs/heads/master@{#416597}
This commit is contained in:
238
docs/callback.md
238
docs/callback.md
@ -1,34 +1,33 @@
|
||||
# base::Callback<> and base::Bind()
|
||||
|
||||
# Introduction
|
||||
## Introduction
|
||||
|
||||
The templated Callback class is a generalized function object. Together
|
||||
with the `Bind()` function in bind.h, they provide a type-safe method for
|
||||
The templated `Callback<>` class is a generalized function object. Together with
|
||||
the `Bind()` function in base/bind.h, they provide a type-safe method for
|
||||
performing partial application of functions.
|
||||
|
||||
Partial application (or "currying") is the process of binding a subset of
|
||||
a function's arguments to produce another function that takes fewer
|
||||
arguments. This can be used to pass around a unit of delayed execution,
|
||||
much like lexical closures are used in other languages. For example, it
|
||||
is used in Chromium code to schedule tasks on different MessageLoops.
|
||||
Partial application (or "currying") is the process of binding a subset of a
|
||||
function's arguments to produce another function that takes fewer arguments.
|
||||
This can be used to pass around a unit of delayed execution, much like lexical
|
||||
closures are used in other languages. For example, it is used in Chromium code
|
||||
to schedule tasks on different MessageLoops.
|
||||
|
||||
A callback with no unbound input parameters (`base::Callback<void()>`)
|
||||
is called a `base::Closure`. Note that this is NOT the same as what other
|
||||
languages refer to as a closure -- it does not retain a reference to its
|
||||
enclosing environment.
|
||||
A callback with no unbound input parameters (`Callback<void()>`) is called a
|
||||
`Closure`. Note that this is NOT the same as what other languages refer to as a
|
||||
closure -- it does not retain a reference to its enclosing environment.
|
||||
|
||||
## MEMORY MANAGEMENT AND PASSING
|
||||
### 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 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.
|
||||
The reason to pass via a const-reference is to avoid unnecessary AddRef/Release
|
||||
pairs to the internal state.
|
||||
|
||||
## Quick reference for basic stuff
|
||||
|
||||
# Quick reference for basic stuff
|
||||
|
||||
## BINDING A BARE FUNCTION
|
||||
### Binding A Bare Function
|
||||
|
||||
```cpp
|
||||
int Return5() { return 5; }
|
||||
@ -36,10 +35,10 @@ base::Callback<int()> func_cb = base::Bind(&Return5);
|
||||
LOG(INFO) << func_cb.Run(); // Prints 5.
|
||||
```
|
||||
|
||||
## BINDING A CLASS METHOD
|
||||
### Binding A Class Method
|
||||
|
||||
The first argument to bind is the member function to call, the second is
|
||||
the object on which to call it.
|
||||
The first argument to bind is the member function to call, the second is the
|
||||
object on which to call it.
|
||||
|
||||
```cpp
|
||||
class Ref : public base::RefCountedThreadSafe<Ref> {
|
||||
@ -57,7 +56,7 @@ error. If you're passing between threads, be sure it's
|
||||
RefCountedThreadSafe! See "Advanced binding of member functions" below if
|
||||
you don't want to use reference counting.
|
||||
|
||||
## RUNNING A CALLBACK
|
||||
### Running A Callback
|
||||
|
||||
Callbacks can be run with their `Run` method, which has the same
|
||||
signature as the template argument to the callback.
|
||||
@ -78,7 +77,7 @@ void DoSomething(const base::Callback<double(double)>& callback) {
|
||||
}
|
||||
```
|
||||
|
||||
## PASSING UNBOUND INPUT PARAMETERS
|
||||
### Passing Unbound Input Parameters
|
||||
|
||||
Unbound parameters are specified at the time a callback is `Run()`. They are
|
||||
specified in the `Callback` template type:
|
||||
@ -89,12 +88,11 @@ base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc);
|
||||
cb.Run(23, "hello, world");
|
||||
```
|
||||
|
||||
## PASSING BOUND INPUT PARAMETERS
|
||||
### Passing Bound Input Parameters
|
||||
|
||||
Bound parameters are specified when you create the callback as arguments
|
||||
to `Bind()`. They will be passed to the function and the `Run()`ner of the
|
||||
callback doesn't see those values or even know that the function it's
|
||||
calling.
|
||||
Bound parameters are specified when you create the callback as arguments to
|
||||
`Bind()`. They will be passed to the function and the `Run()`ner of the callback
|
||||
doesn't see those values or even know that the function it's calling.
|
||||
|
||||
```cpp
|
||||
void MyFunc(int i, const std::string& str) {}
|
||||
@ -102,8 +100,8 @@ base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world");
|
||||
cb.Run();
|
||||
```
|
||||
|
||||
A callback with no unbound input parameters (`base::Callback<void()>`)
|
||||
is called a `base::Closure`. So we could have also written:
|
||||
A callback with no unbound input parameters (`base::Callback<void()>`) is called
|
||||
a `base::Closure`. So we could have also written:
|
||||
|
||||
```cpp
|
||||
base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
|
||||
@ -116,10 +114,10 @@ pointer.
|
||||
base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
|
||||
```
|
||||
|
||||
## PARTIAL BINDING OF PARAMETERS
|
||||
### Partial Binding Of Parameters
|
||||
|
||||
You can specify some parameters when you create the callback, and specify
|
||||
the rest when you execute the callback.
|
||||
You can specify some parameters when you create the callback, and specify the
|
||||
rest when you execute the callback.
|
||||
|
||||
```cpp
|
||||
void MyFunc(int i, const std::string& str) {}
|
||||
@ -130,44 +128,43 @@ cb.Run("hello world");
|
||||
When calling a function bound parameters are first, followed by unbound
|
||||
parameters.
|
||||
|
||||
## Quick reference for advanced binding
|
||||
|
||||
# Quick reference for advanced binding
|
||||
|
||||
## BINDING A CLASS METHOD WITH WEAK POINTERS
|
||||
### Binding A Class Method With Weak Pointers
|
||||
|
||||
```cpp
|
||||
base::Bind(&MyClass::Foo, GetWeakPtr());
|
||||
``
|
||||
```
|
||||
|
||||
The callback will not be run if the object has already been destroyed.
|
||||
DANGER: weak pointers are not threadsafe, so don't use this
|
||||
when passing between threads!
|
||||
**DANGER**: weak pointers are not threadsafe, so don't use this when passing between
|
||||
threads!
|
||||
|
||||
## BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT
|
||||
### Binding A Class Method With Manual Lifetime Management
|
||||
|
||||
```cpp
|
||||
base::Bind(&MyClass::Foo, base::Unretained(this));
|
||||
```
|
||||
|
||||
This disables all lifetime management on the object. You're responsible
|
||||
for making sure the object is alive at the time of the call. You break it,
|
||||
you own it!
|
||||
This disables all lifetime management on the object. You're responsible for
|
||||
making sure the object is alive at the time of the call. You break it, you own
|
||||
it!
|
||||
|
||||
## BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS
|
||||
### Binding A Class Method And Having The Callback Own The Class
|
||||
|
||||
```cpp
|
||||
MyClass* myclass = new MyClass;
|
||||
base::Bind(&MyClass::Foo, base::Owned(myclass));
|
||||
```
|
||||
|
||||
The object will be deleted when the callback is destroyed, even if it's
|
||||
not run (like if you post a task during shutdown). Potentially useful for
|
||||
"fire and forget" cases.
|
||||
The object will be deleted when the callback is destroyed, even if it's not run
|
||||
(like if you post a task during shutdown). Potentially useful for "fire and
|
||||
forget" cases.
|
||||
|
||||
## IGNORING RETURN VALUES
|
||||
### Ignoring Return Values
|
||||
|
||||
Sometimes you want to call a function that returns a value in a callback
|
||||
that doesn't expect a return value.
|
||||
Sometimes you want to call a function that returns a value in a callback that
|
||||
doesn't expect a return value.
|
||||
|
||||
```cpp
|
||||
int DoSomething(int arg) { cout << arg << endl; }
|
||||
@ -175,13 +172,13 @@ base::Callback<void(int)> cb =
|
||||
base::Bind(base::IgnoreResult(&DoSomething));
|
||||
```
|
||||
|
||||
# Quick reference for binding parameters to Bind()
|
||||
## Quick reference for binding parameters to Bind()
|
||||
|
||||
Bound parameters are specified as arguments to `Bind()` and are passed to the
|
||||
function. A callback with no parameters or no unbound parameters is called a
|
||||
`Closure` (`base::Callback<void()>` and `base::Closure` are the same thing).
|
||||
|
||||
## PASSING PARAMETERS OWNED BY THE CALLBACK
|
||||
### Passing Parameters Owned By The Callback
|
||||
|
||||
```cpp
|
||||
void Foo(int* arg) { cout << *arg << endl; }
|
||||
@ -189,10 +186,10 @@ int* pn = new int(1);
|
||||
base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
|
||||
```
|
||||
|
||||
The parameter will be deleted when the callback is destroyed, even if it's
|
||||
not run (like if you post a task during shutdown).
|
||||
The parameter will be deleted when the callback is destroyed, even if it's not
|
||||
run (like if you post a task during shutdown).
|
||||
|
||||
## PASSING PARAMETERS AS A scoped_ptr
|
||||
### Passing Parameters As A unique_ptr
|
||||
|
||||
```cpp
|
||||
void TakesOwnership(std::unique_ptr<Foo> arg) {}
|
||||
@ -201,12 +198,12 @@ std::unique_ptr<Foo> f(new Foo);
|
||||
base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
|
||||
```
|
||||
|
||||
Ownership of the parameter will be with the callback until the callback is
|
||||
run, and then ownership is passed to the callback function. This means the
|
||||
callback can only be run once. If the callback is never run, it will delete
|
||||
the object when it's destroyed.
|
||||
Ownership of the parameter will be with the callback until the callback is run,
|
||||
and then ownership is passed to the callback function. This means the callback
|
||||
can only be run once. If the callback is never run, it will delete the object
|
||||
when it's destroyed.
|
||||
|
||||
## PASSING PARAMETERS AS A scoped_refptr
|
||||
### Passing Parameters As A scoped_refptr
|
||||
|
||||
```cpp
|
||||
void TakesOneRef(scoped_refptr<Foo> arg) {}
|
||||
@ -214,10 +211,10 @@ scoped_refptr<Foo> f(new Foo)
|
||||
base::Closure cb = base::Bind(&TakesOneRef, f);
|
||||
```
|
||||
|
||||
This should "just work." The closure will take a reference as long as it
|
||||
is alive, and another reference will be taken for the called function.
|
||||
This should "just work." The closure will take a reference as long as it is
|
||||
alive, and another reference will be taken for the called function.
|
||||
|
||||
## PASSING PARAMETERS BY REFERENCE
|
||||
### Passing Parameters By Reference
|
||||
|
||||
Const references are *copied* unless `ConstRef` is used. Example:
|
||||
|
||||
@ -232,40 +229,38 @@ has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb"
|
||||
has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa"
|
||||
```
|
||||
|
||||
Normally parameters are copied in the closure. DANGER: ConstRef stores a
|
||||
const reference instead, referencing the original parameter. This means
|
||||
that you must ensure the object outlives the callback!
|
||||
Normally parameters are copied in the closure.
|
||||
**DANGER**: ConstRef stores a const reference instead, referencing the original
|
||||
parameter. This means that you must ensure the object outlives the callback!
|
||||
|
||||
## Implementation notes
|
||||
|
||||
# Implementation notes
|
||||
### Where Is This Design From:
|
||||
|
||||
## 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.
|
||||
|
||||
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:
|
||||
### How The Implementation Works:
|
||||
|
||||
There are three main components to the system:
|
||||
1) The Callback classes.
|
||||
2) The `Bind()` functions.
|
||||
3) The arguments wrappers (e.g., `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 `BindState<>*`. In the context of the constructor,
|
||||
the static type of this `BindState<>` pointer uniquely identifies the
|
||||
function it is representing, all its bound parameters, and a `Run()` method
|
||||
that is capable of invoking the target.
|
||||
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 `BindState<>*`. In the context of the constructor, the static
|
||||
type of this `BindState<>` pointer uniquely identifies the function it is
|
||||
representing, all its bound parameters, and a `Run()` method that is capable of
|
||||
invoking the target.
|
||||
|
||||
`Callback`'s constructor takes the `BindState<>*` that has the full static type
|
||||
and erases the target function type as well as the types of the bound
|
||||
parameters. It does this by storing a pointer to the specific `Run()`
|
||||
function, and upcasting the state of `BindState<>*` to a
|
||||
`BindStateBase*`. This is safe as long as this `BindStateBase` pointer
|
||||
is only used with the stored `Run()` pointer.
|
||||
parameters. It does this by storing a pointer to the specific `Run()` function,
|
||||
and upcasting the state of `BindState<>*` to a `BindStateBase*`. This is safe as
|
||||
long as this `BindStateBase` pointer is only used with the stored `Run()`
|
||||
pointer.
|
||||
|
||||
To `BindState<>` objects are created inside the `Bind()` functions.
|
||||
These functions, along with a set of internal templates, are responsible for
|
||||
@ -281,67 +276,64 @@ These functions, along with a set of internal templates, are responsible for
|
||||
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.
|
||||
These copies are created even if the function takes parameters as const
|
||||
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. These
|
||||
copies are created even if the function takes parameters as const
|
||||
references. (Binding to non-const references is forbidden, see bind.h.)
|
||||
|
||||
To change this behavior, we introduce a set of argument wrappers
|
||||
(e.g., `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.
|
||||
To change this behavior, we introduce a set of argument wrappers (e.g.,
|
||||
`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.
|
||||
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?
|
||||
### 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.
|
||||
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.
|
||||
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.
|
||||
`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.
|
||||
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
|
||||
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 (e.g.,
|
||||
`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
|
||||
become a source of errors. Removing support for these features actually
|
||||
allows for a simpler implementation, and a terser Currying API.
|
||||
become a source of errors. Removing support for these features actually allows
|
||||
for a simpler implementation, and a terser Currying API.
|
||||
|
||||
## WHY NOT GOOGLE CALLBACKS?
|
||||
### 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.
|
||||
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
|
||||
### Missing Functionality
|
||||
- Invoking the return of `Bind`. `Bind(&foo).Run()` does not work;
|
||||
- Binding arrays to functions that take a non-const pointer.
|
||||
Example:
|
||||
|
Reference in New Issue
Block a user