Index: docs/callback.md |
diff --git a/docs/callback.md b/docs/callback.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c5cc5b4d0108e6b9e67f02ee620457c96586d675 |
--- /dev/null |
+++ b/docs/callback.md |
@@ -0,0 +1,433 @@ |
+# base::Callback<> and base::Bind() |
+ |
+## Introduction |
+ |
+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. |
+ |
+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. |
+ |
+### OneShotCallback<> and RepeatingCallback<> |
+ |
+`OneShotCallback<>` and `RepeatingCallback<>` are next gen callback classes, |
+which are under development. |
+ |
+`OneShotCallback<>` is created by `BindOneShot()`, that is a restricted variant |
+of `Callback<>` that is a move-only type and can run only once. It can handle |
+movable types better as its bound parameter, and has clearer lifetime. Thus, |
+thread hopping and result handning of an asynchronous operation are a good fit |
+for it. |
+ |
+`RepeatingCallback<>` is created by `BindRepeating()`, that is a loose variant. |
+Its internal storage is ref-counted and `RepeatingCallback<>` itself is a |
+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. |
+ |
+`RepeatingCallback<>` is convertible to `OneShotCallback<>` by the implicit |
+conversion. |
+ |
+`Callback<>` is an alias of `RepeatingCallback<>` and `Bind()` is an alias of |
+`BindRepeating()` for a historical reason. |
+ |
+### Memory management and passing |
+ |
+The `RepeatingCallback` objects should be passed by const-reference or by value, |
+and stored by copy or by move. The `OneShotCallback` object should be passed by |
+value and stored by move. They internally store their state via a refcounted |
+class and thus do not need to be deleted. |
+ |
+## Quick reference for basic usage |
+ |
+### Binding a bare function |
+ |
+```cpp |
+int Return5() { return 5; } |
+Callback<int()> func_cb = Bind(&Return5); |
+LOG(INFO) << func_cb.Run(); // Prints 5. |
+ |
+OneShotCallback<int()> func_cb2 = BindOneShot(&Return5); |
+LOG(INFO) << std::move(func_cb2).Run(); // Prints 5. |
vabr (Chromium)
2016/08/24 11:44:06
func_cb2 is neither stored nor passed here (it is
tzik
2016/08/30 11:31:41
Since func_cb2 is a variant of Callback that can b
|
+``` |
+ |
+### Binding a captureless lambda |
+ |
+```cpp |
+Callback<int()> lambda_cb = Bind([] { return 4; }); |
+LOG(INFO) << lambda_cb.Run(); // Print 4. |
+ |
+OneShotCallback<int()> lambda_cb2 = BindOneShot([] { 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 RefCountedThreadSafe<Ref> { |
+ public: |
+ int Foo() { return 3; } |
+}; |
+ |
+scoped_refptr<Ref> ref = new 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. |
+ |
+### Running a Callback |
+ |
+Callbacks can be run with their "Run" method, which has the same signature as |
+the template argument to the callback. |
+ |
+`RepeatingCallback<>` can be run directly. |
+ |
+```cpp |
+void DoSomething(const RepeatingCallback<void(int, std::string)>& callback) { |
+ callback.Run(5, "hello"); |
+} |
+``` |
+ |
+```cpp |
+void DoSomething(const RepeatingCallback<double(double)>& callback) { |
+ double myresult = callback.Run(3.14159); |
+ myresult += callback.Run(2.71828); |
+} |
+``` |
+ |
+`OneShotCallback<>` can be run when it's a rvalue. Use `std::move` or |
+`ResetAndReturn` to run it. |
+ |
+```cpp |
+void DoSomething(OneShotCallback<void(int, double)> callback) { |
+ std::move(callback).Run(1, 0.1); |
+} |
+``` |
+ |
+```cpp |
+void DoSomething(OneShotCallback<void()> callback) { |
+ ResetAndReturn(&callback).Run(); |
+} |
+``` |
+ |
+`RepeatingCallback<>` can be run more than once (they don't get deleted or |
+marked when run). However, this precludes using `Passed` (see below). |
+ |
+### Passing unbound input parameters |
+ |
+Unbound parameters are specified at the time a callback is Run(). They are |
+specified in the Callback template type: |
+ |
+```cpp |
+void MyFunc(int i, const std::string& str) {} |
+Callback<void(int, const std::string&)> cb = Bind(&MyFunc); |
+cb.Run(23, "hello, world"); |
+``` |
+ |
+### 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 runner 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) {} |
+Callback<void()> cb = Bind(&MyFunc, 23, "hello world"); |
+cb.Run(); |
+``` |
+ |
+A callback with no unbound input parameters (`Callback<void()>`, |
+`OneShotCallback<void()>` and `RepeatingCallback<void()>`) is called a |
+`Closure`, `OneShotClosure` and `RepeatingClosure`, respectively. |
+So we could have also written: |
+ |
+```cpp |
+Closure cb = Bind(&MyFunc, 23, "hello world"); |
+``` |
+ |
+When calling member functions, bound parameters just go after the object |
+pointer. |
+ |
+```cpp |
+Closure cb = Bind(&MyClass::MyFunc, this, 23, "hello world"); |
+``` |
+ |
+### PARTIAL BINDING OF PARAMETERS |
+ |
+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) {} |
+Callback<void(const std::string&)> cb = Bind(&MyFunc, 23); |
+cb.Run("hello world"); |
+``` |
+ |
+## Quick reference for advanced binding |
+ |
+### Binding a class method with weak pointers |
+ |
+```cpp |
+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 you pass it |
+between threads! |
+ |
+### Binding a class method with manual lifetime management |
+ |
+```cpp |
+Bind(&MyClass::Foo, 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! |
+ |
+### Binding a class method and having the callback own the instance |
+ |
+```cpp |
+MyClass* myclass = new 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. |
+ |
+```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 |
+doesn't expect a return value. |
+ |
+```cpp |
+int DoSomething(int arg) { cout << arg << endl; } |
+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` (`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); |
+Closure foo_callback = Bind(&foo, 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). |
+ |
+### Passing parameters as a unique_ptr |
+ |
+```cpp |
+void TakesOwnership(std::unique_ptr<Foo> arg) {} |
+std::unique_ptr<Foo> f(new Foo); |
+// f becomes null during the following call. |
+RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(std::move(f))); |
+``` |
+ |
+Ownership of the parameter will be with the callback until it is run, when |
+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. |
+ |
+```cpp |
+void TakesOwnership(std::unique_ptr<Foo> arg) {} |
+std::unique_ptr<Foo> f(new Foo); |
+// f becomes null during the following call. |
+OneShotClosure cb = BindOneShot(&TakesOwnership, std::move(f)); |
+``` |
+ |
+Parameters bound by `BindOneShot()` are passed out even without `Passed`. |
+ |
+### Passing movable objects |
+ |
+```cpp |
+void TakesMovableObject(std::vector<char> obj) {} |
+std::vector<char> buf; |
+Closure cb = Bind(&TakesMovableObject, Passed(&buf)); |
+std::move(cb).Run(); |
+``` |
+ |
+When a bound argument is wrapped by `Passed()`, `Bind` moves the argument into |
+its internal storage rather than copying it, and moves out it when the callback |
+is run. |
+ |
+ |
+```cpp |
+void TakesMovableObject(std::vector<char> obj) {} |
+std::vector<char> buf; |
+OneShotClosure cb = BindOneShot(&TakesMovableObject, std::move(buf)); |
+std::move(cb).Run(); |
+``` |
+ |
+`OneShotCallback` moves out bound arguments even without `Passed`. |
+ |
+ |
+```cpp |
+void TakesMovableObject(std::vector<char> buf) {} |
+std::vector<char> buf; |
+Closure cb = Bind(&TakesMovableObject, std::move(buf)); |
+cb.Run(); |
+``` |
+ |
+In contrast, when an object is bound with `std::move` into a `RepeatingCallback`, |
+the bound object is copied when the callback is run. |
+ |
+### Passing parameters as a scoped_refptr |
+ |
+```cpp |
+void TakesOneRef(scoped_refptr<Foo> arg) {} |
+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: |
+ |
+```cpp |
+void foo(const int& arg) { printf("%d %p\n", arg, &arg); } |
+int n = 1; |
+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" |
+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! |
+ |
+## Implementation notes |
+ |
+### 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. |
+ |
+### 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) { |
+ 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 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. |
+ |
+### 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. `Callback` has a constructor that takes a `BindStateBase*` |
+and `&Invoker::Run`. A `BindState<>` holds a function object to run, and also |
+holds bound parameters. `BindStateBase` is the base class of of `BindState<>`, |
+without type information of bound data. In the context of the constructor of |
+`Callback`, `Invoker::Run` has the static type of `BindState<>` that identifies |
+the function it is representing and all its bound parameters. |
+ |
+`Bind()` creates the `BindState<>` that has the full static type, and erases the |
+target function type as well as the type of bound parameters. It does this by |
+taking a pointer to the specific `Invoker::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 `Invoker::Run()` pointer. |
+ |
+To `BindState<>` objects are created inside the `Bind()` functions. |
+These functions, along with a set of internal templates, are responsible for |
+ |
+ - Unwrapping the function signature into return type, and parameters |
+ - Determining the number of parameters that are bound |
+ - Creating the BindState storing the bound parameters |
+ - Performing compile-time asserts to avoid error-prone behavior |
+ - Returning an `Callback<>` with an arity matching the number of unbound |
+ parameters and that knows the correct refcounting semantics for the |
+ target object if we are binding a method. |
+ |
+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. |
+ |
+These types are passed to the Unwrap() functions, and the IsWeakReceiver<> |
+traits respectively to modify the behavior of Bind(). |
+ |
+`ConstRef()` is similar to std::cref. `Unretained()` is specific to Chromium. |
+`Owned()` and `RetainedRef()` let `BindState<>` own the exclusive or shared |
vabr (Chromium)
2016/08/24 11:44:06
optional nit: "own the exclusive or shared ownersh
tzik
2016/08/30 11:31:41
Done.
|
+ownership and pass the bound item as a raw pointer to the target function. |