~ If you don't use the low-level C++ bindings you may stop reading now ~
TLDR: Over the next few weeks, we're making the syntax for FIDL calls, events, and replies more consistent and extensible.
Tracking bug: fxbug.dev/85688
LLCPP has a relatively large API surface compared to other bindings due to its extended features, in particular different ways to initiate an interaction (asynchronous, synchronous, managed allocation, caller allocation, …). They are currently exposed somewhat arbitrarily using overloads and method name suffixes, leading to bloated and complex interfaces. Take for example a FIDL protocol MyProtocol with a simple two-way method Foo. In a fidl::WireClient<MyProtocol>, there are more than 4 different ways to make the call:
Ahead of exposing LLCPP to the SDK and out-of-tree users, we would like to rationalize the way different flavors as presented to the user, in particular:
Reduce the amount of future API churn by strategically placing extension points in the LLCPP API.
Increase the similarity between a driver in-process messaging layer and the regular IPC messaging layer.
Harmonize caller-allocated flavors which take a byte buffer and FIDL arenas which similarly is a tool for reducing heap allocation.
See the design described in fxbug.dev/85688 for details. Here we present the most significant changes:
Right now some client types use dot (".") to make calls, while others expose it behind a dereference operator ("->"). We're changing the syntax for all client calls, and for sending events, to use the arrow:
this in turn allows us to…
For example, instead of differentiating between managed flavors and caller-allocating flavors purely based on overloads, the caller-allocating flavors will be made available on an interface returned by a .buffer(...) accessor:
Similarly, the synchronous calls in a fidl::WireClient would be hidden under a .sync() accessor:
As a bonus point, the accessors compose, so one could write:
Similar changes would be made to server completers and event senders.
No proactive migration/changes are required on your part. The FIDL team will be migrating code on users' behalf. We may ping code maintainers for review or context in specific cases.
If you have in-flight CLs that abruptly stop compiling, it could be due to one of the in-progress changes here. For example, changing "." to "->" when making calls or sending events may help. As of this email, fidl::WireCall have switched over to arrow operators, and fxrev.dev/591661 is an in-progress change migrating caller-allocating flavors to .buffer().
Please let us know on fidl...@fuchsia.dev if you have questions or suggestions. Thanks.
Cheers,
Yifei
After:
Example:
~ If you don't use the low-level C++ bindings you may stop reading now ~
TLDR:
We added .sync() to fidl::WireClient and fidl::WireSharedClient, to support making synchronous calls over the same endpoint that is managed by the client.
Today a WireClient or WireSharedClient exposes both synchronous and asynchronous calls behind the same "->" operator - the synchronous ones are affixed with _Sync in their name. If you have been writing code with ->Foo_Sync(...) calls, those will be changed to .sync()->Foo(...) over the next few days:
Why are we doing this:
When an application already has an async_dispatcher_t, synchronous calls should be avoided where possible, since they introduce blocking behavior. However, since synchronous calls have a straightforward control flow and cleaner syntax compared to async code, they may be preferable in unit tests, and we currently have ~14 files using them in-tree.
This migration captures the above principle in the LLCPP API: when writing my_client->SomeMethod(...), the functions exposed are always asynchronous (or one-way). The synchronous methods are still supported, but they are now tucked away behind a .sync() accessor, and we could later decide whether to enable/disable this feature on different clients.
Please let us know on fidl...@fuchsia.dev if you have questions or suggestions. Thanks.
Cheers, Yifei
~ If you don't use the low-level C++ bindings you may stop reading now ~
TLDR:
We added fidl::WireSendEvent(const fidl::ServerEnd<Protocol>& endpoint) and fidl::WireSendEvent(const fidl::ServerBindingRef<Protocol>& binding_ref) to support sending events over an endpoint or a server binding reference.
The existing usages of sending events will be migrated over the next few days.
Example:
There's now one consistent syntax for sending events: wrap the corresponding endpoint/binding reference in fidl::WireSendEvent to obtain an interface for sending events. One may also write fidl::WireSendEvent(..).buffer(..) to send events using caller-controlled allocation, similar to fidl::WireCall.
Why are we doing this:
Apart from more consistent syntax, the stronger underlying motivation is to decouple the LLCPP runtime from particular flavors of domain object types. For instance, fidl::ServerBindingRef previously exposed an operator->() to send events using the wire domain object types (those are generated under the fuchsia_my_lib::wire::... namespace). We are working on a more ergonomic set of domain objects, called "natural types", similar to those found in HLCPP, and it should be possible to send events using those types over the same binding reference, without coupling fidl::ServerBindingRef to either.
Using a free function syntax (fidl::WireSendEvent(...)) allows us to subsequently introduce other free functions to work with natural types.
Please let us know on fidl...@fuchsia.dev if you have questions or suggestions. Thanks.
Cheers, Yifei