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

Unified Diff: docs/callback.md

Issue 2042223002: Introduce OnceClosure and BindOnce (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update docs Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« base/callback_internal.cc ('K') | « base/callback_unittest.nc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: docs/callback.md
diff --git a/docs/callback.md b/docs/callback.md
new file mode 100644
index 0000000000000000000000000000000000000000..0090ffb1818c2ce42269ad2a4a17736788db16d6
--- /dev/null
+++ b/docs/callback.md
@@ -0,0 +1,360 @@
+# 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()`. `OneShotCallback<>` is a
+restricted variant of `Callback<>` that is a move-only type and can run only
+once. It can handle move-only types better as its bound parameter, and has
+clearer lifetime. Thus, thread hopping or result handning of an asynchronous
+operation is a good fit for it.
+
+`RepeatingCallback<>` is created by `BindRepeating()`. `RepeatingCallback<>` 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 `Callback` objects themselves should be passed by const-reference or by
+value, and stored by copy or 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.
+```
+
+### Binding a captureless lambda
+
+```cpp
+OneShotCallback<int()> lambda_cb = BindOneShot([] { return 3; });
+LOG(INFO) << std::move(lambda_cb).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 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.
+
+*** note
+**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 class
+
+```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 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.
+
+### 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.
+
+*** note
+**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.
+
+### 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
+ownership and pass the bound item as a raw pointer to the target function.
« base/callback_internal.cc ('K') | « base/callback_unittest.nc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698