A new keyword associated is introduced for interface pointer/request fields. For example:
It means the interface impl/client will communicate using the same message pipe over which the associated interface pointer/request is passed.
When generating C++ bindings, associated interface pointer of Bar is mapped to BarAssociatedPtrInfo (which is an alias of mojo::AssociatedInterfacePtrInfo<Bar>); associated interface request to BarAssociatedRequest (which is an alias of mojo::AssociatedInterfaceRequest<Bar>).
Assume you have already got an InterfacePtr<Foo> foo_ptr, and you would like to call GetBar() on it. You can do:
First, the code creates an associated interface of type Bar. It looks very similar to what you would do to setup a non-associated interface. An important difference is that one of the two associated endpoints (either bar_request or bar_ptr_info) must be sent over another interface. That is how the interface is associated with an existing message pipe.
It should be noted that you cannot call bar_ptr->DoSomething() before passing bar_request. This is required by the FIFO-ness guarantee: at the receiver side, when the message of DoSomething call arrives, we want to dispatch it to the corresponding AssociatedBinding<Bar> before processing any subsequent messages. If bar_request is in a subsequent message, message dispatching gets into a deadlock. On the other hand, as soon as bar_request is sent, bar_ptr is usable. There is no need to wait until bar_request is bound to an implementation at the remote side.
A MakeRequest overload which takes an AssociatedInterfacePtr pointer (instead of an AssociatedInterfacePtrInfo pointer) is provided to make the code a little shorter. The following code achieves the same purpose:
The implementation of Foo looks like this:
In this example, bar_binding_’s lifespan is tied to that of FooImpl. But you don’t have to do that. You can, for example, pass bar2 to another thread to bind to an AssociatedBinding<Bar> there.
When the underlying message pipe is disconnected (e.g., foo_ptr or foo_binding_ is destroyed), all associated interface endpoints (e.g., bar_ptr and bar_binding_) will receive a connection error.
Similarly, assume you have already got an InterfacePtr<Foo> foo_ptr, and you would like to call SetBar() on it. You can do:
The following code achieves the same purpose:
Therefore, performance-wise associated interfaces are better suited for scenarios where message receiving happens on the master thread.
(someone please verify - adding this after running into issues trying to test)
Testing associated interfaces requires that a message pipe / router be created, as associated interfaces assume this happens elsewhere. So use mojo::MakeIsolatedRequest for either:
As long as there is a 'currently called' binding that was created from this method (which creates the message pipe/router internally), then all further calls to associated bindings will use that message router.