| Index: docs/callback.md
|
| diff --git a/docs/callback.md b/docs/callback.md
|
| index af141b5d62f829929b0122582ec5c0b17280bcf9..02ee1960210cd7e140b3a10d885864a493a9a9e4 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
|
| +`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,
|
| +thread hopping and result handning of an asynchronous operation are a good fit
|
| +for it.
|
| +
|
| +`RepeatingCallback<>` is created by `BindRepeating()` as 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.
|
| +
|
| +The historycal `Callback<>` is `RepeatingCallback<>`. It's an alias of
|
| +`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
|
| +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
|
| +// 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
|
| +// 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,8 +83,22 @@ pairs to the internal state.
|
|
|
| ```cpp
|
| int Return5() { return 5; }
|
| -base::Callback<int()> func_cb = base::Bind(&Return5);
|
| +Callback<int()> func_cb = Bind(&Return5);
|
| LOG(INFO) << func_cb.Run(); // Prints 5.
|
| +
|
| +OnceCallback<int()> func_cb2 = BindOnce(&Return5);
|
| +LOG(INFO) << std::move(func_cb2).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
|
| @@ -41,42 +107,59 @@ 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.
|
| +
|
| +`RepeatingCallback<>` can be run directly.
|
|
|
| ```cpp
|
| -void DoSomething(const base::Callback<void(int, std::string)>& callback) {
|
| +void DoSomething(const RepeatingCallback<void(int, std::string)>& callback) {
|
| 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).
|
| -
|
| ```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);
|
| }
|
| ```
|
|
|
| +`OnceCallback<>` can be run when it's a rvalue. Use `std::move` or
|
| +`ResetAndReturn` to run it.
|
| +
|
| +```cpp
|
| +void DoSomething(OnceCallback<void(int, double)> callback) {
|
| + std::move(callback).Run(1, 0.1);
|
| +}
|
| +```
|
| +
|
| +```cpp
|
| +void DoSomething(OnceCallback<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
|
| @@ -84,66 +167,66 @@ 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");
|
| ```
|
|
|
| ### 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
|
| +`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) {}
|
| -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()>`,
|
| +`OnceCallback<void()>` and `RepeatingCallback<void()>`) is called a
|
| +`Closure`, `OnceClosure` and `RepeatingClosure`, respectively.
|
| +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
|
|
|
| -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) {}
|
| -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.
|
| -
|
| ## 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.
|
| -**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 you pass it
|
| +between 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 +237,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.
|
| +
|
| +```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,26 +258,26 @@ 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
|
| -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 unique_ptr
|
|
|
| @@ -195,25 +285,77 @@ 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(std::move(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 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.
|
| +OnceClosure cb = BindOnce(&TakesOwnership, std::move(f));
|
| +```
|
| +
|
| +Parameters bound by `BindOnce()` 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;
|
| +OnceClosure cb = BindOnce(&TakesMovableObject, std::move(buf));
|
| +std::move(cb).Run();
|
| +```
|
| +
|
| +`OnceCallback` 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)
|
| -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 +363,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,37 +372,68 @@ 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
|
|
|
| -### 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.
|
| +
|
| +### Customizing the behavior
|
|
|
| -The design `Callback` and Bind is heavily influenced by C++'s `tr1::function` /
|
| -`tr1::bind`, and by the "Google Callback" system used inside Google.
|
| +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.
|
| + 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.
|
| -
|
| -`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.
|
| +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
|
| @@ -273,76 +446,19 @@ 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.
|
| -
|
| 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.)
|
| +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 `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.
|
| -
|
| -`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
|
| -void Foo(const char* ptr);
|
| -void Bar(char* ptr);
|
| -Bind(&Foo, "test");
|
| -Bind(&Bar, "test"); // This fails because ptr is not const.
|
| -```
|
| +These types are passed to the Unwrap() functions, and the IsWeakReceiver<>
|
| +traits respectively to modify the behavior of Bind().
|
|
|
| -If you are thinking of forward declaring `Callback` in your own header file,
|
| -please include "base/callback_forward.h" instead.
|
| +`ConstRef()` is similar to std::cref. `Unretained()` is specific to Chromium.
|
| +`Owned()` and `RetainedRef()` let `BindState<>` have the exclusive or shared
|
| +ownership and pass the bound item as a raw pointer to the target function.
|
|
|