0

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:
tzik
2016-09-05 23:51:12 -07:00
committed by Commit bot
parent e7ffbf80d3
commit a431351621

@ -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: