Index: docs/callback.md |
diff --git a/docs/callback.md b/docs/callback.md |
index af141b5d62f829929b0122582ec5c0b17280bcf9..178cc88743497702935aa08f6c42747565f2c413 100644 |
--- a/docs/callback.md |
+++ b/docs/callback.md |
@@ -1,4 +1,4 @@ |
-# base::Callback<> and base::Bind() |
+# Callback<> and Bind() |
## Introduction |
@@ -16,14 +16,66 @@ 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. |
+### OnceCallback<> And RepeatingCallback<> |
+ |
+`OnceCallback<>` and `RepeatingCallback<>` are next gen callback classes, which |
+are under development. |
+ |
+`OnceCallback<>` is created by `BindOnce()` as a restricted variant of |
dcheng
2016/09/08 00:34:40
`OnceCallback<>` is created by `BindOnce()`. This
tzik
2016/10/04 06:02:45
Done.
|
+`Callback<>`. This is a move-only type and can be run only once. It can handle |
+movable types better as its bound parameter, and has clearer lifetime. Thus, |
dcheng
2016/09/08 00:34:40
Maybe clarify what 'better' means here. Perhaps om
tzik
2016/10/04 06:02:46
Done.
|
+thread hopping and result handning of an asynchronous operation are a good fit |
dcheng
2016/09/08 00:34:40
Typo: handling. But I would change this to indicat
tzik
2016/10/04 06:02:46
Done.
|
+for it. |
+ |
+`RepeatingCallback<>` is created by `BindRepeating()` as a loose variant. |
dcheng
2016/09/08 00:34:39
Delete "as a loose variant".
tzik
2016/10/04 06:02:46
Done.
|
+Its internal storage is ref-counted and `RepeatingCallback<>` itself is a |
dcheng
2016/09/08 00:34:40
Technically, the internal storage of OnceCallback
tzik
2016/10/04 06:02:46
Right, removing the refcount gains the binary size
|
+copyable type. It can run more than once. So, it's suitable for event handlers |
+that may happen more than once. It's discouraged to use this for a thread hop, |
+since you cannot predict on which thread the callback object is destroyed. |
+ |
+The historycal `Callback<>` is `RepeatingCallback<>`. It's an alias of |
dcheng
2016/09/08 00:34:40
Typo: historical
Perhaps word this as:
The legac
tzik
2016/10/04 06:02:46
Done.
|
+`RepeatingCallback<>` for a while until the migration is completed, and |
+eventually `OnceCallback<>` will be renamed to `Callback<>`. |
+ |
+`RepeatingCallback<>` is convertible to `OnceCallback<>` by the implicit |
+conversion. |
+ |
### 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. |
+When you take a `Callback` object as a function argument, take it by value if |
dcheng
2016/09/08 00:34:40
Simplify this to:
Pass `Callback` objects by valu
tzik
2016/10/04 06:02:46
Done.
|
+you retain the ownership, otherwise take it by const-reference. |
-The reason to pass via a const-reference is to avoid unnecessary AddRef/Release |
-pairs to the internal state. |
+```cpp |
+// |Foo| just refers |cb|, but doesn't store it nor consume it. So the parameter |
dcheng
2016/09/08 00:34:40
|Foo| refers to |cb| but doesn't store it nor cons
tzik
2016/10/04 06:02:46
OK, let me omit latter one.
|
+// type should be a const-reference. |
+bool Foo(const OnceCallback<void(int)>& cb) { |
+ return cb.is_null(); |
+} |
+ |
+// |Bar| takes the ownership of |cb| and stores |cb| into |g_cb|. Pass the |
+// Callback by value in this case. |
+OnceCallback<void(int)> g_cb; |
+void Bar(OnceCallback<void(int)> cb) { |
+ g_cb = std::move(cb); |
+} |
+ |
+// |Baz| takes the ownership of |cb| and consumes |cb| by Run(). Pass the |
+// Callback by value in this case. |
+void Baz(OnceCallback<void(int)> cb) { |
+ std::move(cb).Run(42); |
+} |
+ |
+// |Qux| takes the ownership of |cb| and forwards it to PostTask, which also |
dcheng
2016/09/08 00:34:40
"transfers ownership to PostTask()."
Otherwise, i
tzik
2016/10/04 06:02:45
Done.
|
+// takes the ownership of |cb|. Pass the Callback by value in this case. |
+void Qux(OnceCallback<void(int)> cb) { |
+ PostTask(FROM_HERE, std::move(cb)); |
+} |
+``` |
+ |
+When you pass a `Callback` object to a function parameter, use `std::move()` if |
+you don't need to keep a reference to it, otherwise, pass the object directly. |
+You may see a compile error when the function requires the exclusive ownership, |
+and you didn't pass the callback by move. |
## Quick reference for basic stuff |
@@ -31,47 +83,68 @@ pairs to the internal state. |
```cpp |
int Return5() { return 5; } |
-base::Callback<int()> func_cb = base::Bind(&Return5); |
+OnceCallback<int()> func_cb = BindOnce(&Return5); |
+LOG(INFO) << std::move(func_cb).Run(); // Prints 5. |
+``` |
+ |
+```cpp |
+int Return5() { return 5; } |
+RepeatingCallback<int()> func_cb = BindRepeating(&Return5); |
LOG(INFO) << func_cb.Run(); // Prints 5. |
``` |
+### Binding A Captureless Lambda |
+ |
+```cpp |
+Callback<int()> lambda_cb = Bind([] { return 4; }); |
+LOG(INFO) << lambda_cb.Run(); // Print 4. |
+ |
+OnceCallback<int()> lambda_cb2 = BindOnce([] { return 3; }); |
+LOG(INFO) << std::move(lambda_cb2).Run(); // Print 3. |
+``` |
+ |
### 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. |
```cpp |
-class Ref : public base::RefCountedThreadSafe<Ref> { |
+class Ref : public RefCountedThreadSafe<Ref> { |
public: |
int Foo() { return 3; } |
- void PrintBye() { LOG(INFO) << "bye."; } |
}; |
scoped_refptr<Ref> ref = new Ref(); |
-base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref); |
+Callback<void()> ref_cb = Bind(&Ref::Foo, ref); |
LOG(INFO) << ref_cb.Run(); // Prints out 3. |
``` |
By default the object must support RefCounted or you will get a compiler |
-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. |
+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 |
-Callbacks can be run with their `Run` method, which has the same |
-signature as the template argument to the callback. |
+Callbacks can be run with their `Run` method, which has the same signature as |
+the template argument to the callback. Note that `OnceCallback::Run` consumes |
+the callback object, and to ensure that, it can be invoked only from rvalue |
dcheng
2016/09/08 00:34:40
consumes the callback object and can only be invok
tzik
2016/10/04 06:02:45
Done.
|
+reference. Use `std::move` on `OnceCallback::Run` invocation. |
```cpp |
-void DoSomething(const base::Callback<void(int, std::string)>& callback) { |
+void DoSomething(const Callback<void(int, std::string)>& callback) { |
callback.Run(5, "hello"); |
} |
+ |
+void DoSomethingOther(OnceCallback<void(int, std::string)> callback) { |
+ std::move(callback).Run(5, "hello"); |
+} |
``` |
-Callbacks can be run more than once (they don't get deleted or marked when |
-run). However, this precludes using base::Passed (see below). |
+RepeatingCallbacks can be run more than once (they don't get deleted or marked |
+when run). However, this precludes using Passed (see below). |
```cpp |
-void DoSomething(const base::Callback<double(double)>& callback) { |
+void DoSomething(const RepeatingCallback<double(double)>& callback) { |
double myresult = callback.Run(3.14159); |
myresult += callback.Run(2.71828); |
} |
@@ -84,7 +157,7 @@ specified in the `Callback` template type: |
```cpp |
void MyFunc(int i, const std::string& str) {} |
-base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc); |
+Callback<void(int, const std::string&)> cb = Bind(&MyFunc); |
cb.Run(23, "hello, world"); |
``` |
@@ -96,22 +169,22 @@ doesn't see those values or even know that the function it's calling. |
```cpp |
void MyFunc(int i, const std::string& str) {} |
-base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world"); |
+Callback<void()> cb = 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 (`Callback<void()>`) is called a |
+`Closure`. So we could have also written: |
```cpp |
-base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); |
+Closure cb = Bind(&MyFunc, 23, "hello world"); |
``` |
When calling member functions, bound parameters just go after the object |
pointer. |
```cpp |
-base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); |
+Closure cb = Bind(&MyClass::MyFunc, this, 23, "hello world"); |
``` |
### Partial Binding Of Parameters |
@@ -121,19 +194,42 @@ rest when you execute the callback. |
```cpp |
void MyFunc(int i, const std::string& str) {} |
-base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23); |
+Callback<void(const std::string&)> cb = Bind(&MyFunc, 23); |
cb.Run("hello world"); |
``` |
When calling a function bound parameters are first, followed by unbound |
parameters. |
+### Move In and Move Out |
+ |
+A parameter of `Bind()` is moved into its internal storage if you use |
dcheng
2016/09/08 00:34:39
What if the parameter is already an rvalue, e.g.
tzik
2016/10/04 06:02:46
Hmm, let me rephrase it to just "if the parameter
|
+`std::move()` for the parameter. |
+ |
+```cpp |
+std::vector<int> v = {1, 2, 3}; |
+// |v| is moved into the internal storage without copy. |
+Bind(&Foo, std::move(v)); |
+``` |
+ |
+A bound object is moved out to the target function if you use `Passed()` for |
+the parameter of `BindRepeating()`, or if you use `BindOnce()`. |
dcheng
2016/09/08 00:34:40
This section is a bit confusing. Passed() can also
tzik
2016/10/04 06:02:45
Right. Rephrased this to
|
+ |
+```cpp |
+void Foo(std::unique_ptr<int>) {} |
+std::unique_ptr<int> p(new int(42)); |
+ |
+// |p| is moved into the internal storage of Bind(), and moved out to |Foo|. |
+BindOnce(&Foo, std::move(p)); |
+BindRepeating(&Foo, Passed(&p)); |
+``` |
+ |
## Quick reference for advanced binding |
### Binding A Class Method With Weak Pointers |
```cpp |
-base::Bind(&MyClass::Foo, GetWeakPtr()); |
+Bind(&MyClass::Foo, GetWeakPtr()); |
``` |
The callback will not be run if the object has already been destroyed. |
@@ -143,7 +239,7 @@ threads! |
### Binding A Class Method With Manual Lifetime Management |
```cpp |
-base::Bind(&MyClass::Foo, base::Unretained(this)); |
+Bind(&MyClass::Foo, Unretained(this)); |
``` |
This disables all lifetime management on the object. You're responsible for |
@@ -154,13 +250,20 @@ it! |
```cpp |
MyClass* myclass = new MyClass; |
-base::Bind(&MyClass::Foo, base::Owned(myclass)); |
+Bind(&MyClass::Foo, 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. |
+Also, smart pointers (e.g. `std::unique_ptr<>`) are supported as the receiver. |
dcheng
2016/09/08 00:34:40
Nit: Smart pointers (e.g. ...) are also supported
tzik
2016/10/04 06:02:45
Done.
|
+ |
+```cpp |
+std::unique_ptr<MyClass> myclass(new MyClass); |
+Bind(&MyClass::Foo, std::move(myclass)); |
+``` |
+ |
### Ignoring Return Values |
Sometimes you want to call a function that returns a value in a callback that |
@@ -168,22 +271,22 @@ doesn't expect a return value. |
```cpp |
int DoSomething(int arg) { cout << arg << endl; } |
-base::Callback<void(int)> cb = |
- base::Bind(base::IgnoreResult(&DoSomething)); |
+Callback<void(int)> cb = |
+ Bind(IgnoreResult(&DoSomething)); |
``` |
## 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). |
+`Closure` (`Callback<void()>` and `Closure` are the same thing). |
### Passing Parameters Owned By The Callback |
```cpp |
void Foo(int* arg) { cout << *arg << endl; } |
int* pn = new int(1); |
-base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); |
+Closure foo_callback = Bind(&foo, Owned(pn)); |
``` |
The parameter will be deleted when the callback is destroyed, even if it's not |
@@ -195,7 +298,7 @@ run (like if you post a task during shutdown). |
void TakesOwnership(std::unique_ptr<Foo> arg) {} |
std::unique_ptr<Foo> f(new Foo); |
// f becomes null during the following call. |
-base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); |
+RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f)); |
``` |
Ownership of the parameter will be with the callback until the callback is run, |
@@ -207,13 +310,22 @@ when it's destroyed. |
```cpp |
void TakesOneRef(scoped_refptr<Foo> arg) {} |
-scoped_refptr<Foo> f(new Foo) |
-base::Closure cb = base::Bind(&TakesOneRef, f); |
+scoped_refptr<Foo> f(new Foo); |
+Closure cb = 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. |
+```cpp |
+void DontTakeRef(Foo* arg) {} |
+scoped_refptr<Foo> f(new Foo); |
+Closure cb = Bind(&DontTakeRef, RetainedRef(f)); |
+``` |
+ |
+`RetainedRef` holds a reference to the object and passes a raw pointer to |
+the object when the Callback is run. |
+ |
### Passing Parameters By Reference |
Const references are *copied* unless `ConstRef` is used. Example: |
@@ -221,8 +333,8 @@ Const references are *copied* unless `ConstRef` is used. Example: |
```cpp |
void foo(const int& arg) { printf("%d %p\n", arg, &arg); } |
int n = 1; |
-base::Closure has_copy = base::Bind(&foo, n); |
-base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); |
+Closure has_copy = Bind(&foo, n); |
+Closure has_ref = Bind(&foo, ConstRef(n)); |
n = 2; |
foo(n); // Prints "2 0xaaaaaaaaaaaa" |
has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" |
@@ -230,8 +342,9 @@ 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! |
+**DANGER**: `ConstRef` stores a const reference instead, referencing the |
+original parameter. This means that you must ensure the object outlives the |
+callback! |
## Implementation notes |
@@ -240,27 +353,54 @@ parameter. This means that you must ensure the object outlives the callback! |
The design `Callback` and Bind is heavily influenced by C++'s `tr1::function` / |
`tr1::bind`, and by the "Google Callback" system used inside Google. |
+### Customizing the behavior |
+ |
+There are several injection points that controls `Bind` behavior from outside of |
+its implementation. |
+ |
+```cpp |
+template <typename Receiver> |
+struct IsWeakReceiver { |
+ static constexpr bool value = false; |
+}; |
+ |
+template <typename Obj> |
+struct UnwrapTraits { |
+ template <typename T> |
+ T&& Unwrap(const T&& obj) { |
dcheng
2016/09/08 00:34:40
Just curious: why is this a const rvalue reference
tzik
2016/10/04 06:02:46
Oh, right it's a bug. Fixed.
|
+ return std::forward<T>(obj); |
+ } |
+}; |
+``` |
+ |
+If `IsWeakReceiver<Receiver>::value` is true on a receiver of a method, `Bind` |
+checks if the receiver is null and cancels the invocation if it's null. You can |
dcheng
2016/09/08 00:34:40
Strictly speaking, we don't check if it's null: we
tzik
2016/10/04 06:02:45
Replaced it with "checks if the receiver is evalua
|
+specialize `IsWeakReceiver` to make an external smart pointer as a weak pointer. |
+ |
+`UnwrapTraits<BoundObject>::Unwrap()` is called for each bound arguments right |
+before `Callback` calls the target function. You can specialize this to define |
+an argument wrapper such as Unretained, ConstRef, Owned, RetainedRef and Passed. |
dcheng
2016/09/08 00:34:40
Nit: wrap Unretained and the rest of the list item
tzik
2016/10/04 06:02:46
Done.
|
+ |
### How The Implementation Works: |
There are three main components to the system: |
- 1) The Callback classes. |
+ 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 |
+bound parameters. The `Callback` constructor takes a `BindStateBase*`, which is |
+upcasted from a `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. |
+`Bind()` creates 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. |
To `BindState<>` objects are created inside the `Bind()` functions. |
These functions, along with a set of internal templates, are responsible for |
@@ -273,8 +413,7 @@ These functions, along with a set of internal templates, are responsible for |
parameters and that knows the correct refcounting semantics for the |
target object if we are binding a method. |
-The `Bind` functions do the above using type-inference, and template |
-specializations. |
+The `Bind` functions do the above using type-inference, and variadic templates. |
dcheng
2016/09/08 00:34:40
Nit: this is pre-existing, but remove the comma be
tzik
2016/10/04 06:02:45
Done.
|
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 |
@@ -286,55 +425,13 @@ To change this behavior, we introduce a set of argument wrappers (e.g., |
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. |
+These types are passed to the `Unwrap()` functions to modify the behavior of |
+`Bind()`. The `Unwrap()` 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? |
- |
-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 (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. |
- |
-### 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. |
- |
### Missing Functionality |
- - Invoking the return of `Bind`. `Bind(&foo).Run()` does not work; |
- Binding arrays to functions that take a non-const pointer. |
Example: |
```cpp |