template <typename Protocol>
class Client
Defined at line 118 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
|Client| is a client for sending and receiving FIDL wire messages, that
must be managed and used from a [synchronized async dispatcher][synchronized-dispatcher].
See |SharedClient| for a client that may be moved or cloned to different
dispatchers or arbitrary threads.
Generated FIDL APIs are accessed by 'dereferencing' the client value:
// Creates a client that speaks over |client_end|, on the |my_dispatcher| dispatcher.
fidl::Client client(std::move(client_end), my_dispatcher);
// Call the |Foo| method asynchronously, passing in a callback that will be
// invoked on a dispatcher thread when the server response arrives.
auto status = client->Foo(args, [] (Result result) {});
## Lifecycle
A client must be **bound** to an endpoint before it could be used. This
association between the endpoint and the client is called a "binding".
Binding a client to an endpoint starts the monitoring of incoming messages.
Those messages are appropriately dispatched: to response callbacks, to event
handlers, etc. FIDL methods (asynchronous or synchronous) may only be invoked
on a bound client.
Internally, a client is a lightweight reference to the binding, performing
its duties indirectly through that object, as illustrated by the simplified
diagram below:
references makes
client -------------> binding --------> FIDL call
This means that the client _object_ and the binding have overlapping but
slightly different lifetimes. For example, the binding may terminate in
response to fatal communication errors, leaving the client object alive but
unable to make any calls.
To stop the monitoring of incoming messages, one may **teardown** the
binding. When teardown is initiated, the client will not monitor new messages
on the endpoint. Ongoing callbacks will be allowed to run to completion. When
teardown is complete, further calls on the same client will fail. Unfulfilled
response callbacks will be dropped.
Destruction of a client object will initiate teardown.
Teardown will also be initiated when the binding encounters a terminal error:
- The server-end of the channel was closed.
- An epitaph was received.
- Decoding or encoding failed.
- An invalid or unknown message was encountered.
- Error waiting on, reading from, or writing to the channel.
In this case, the user will be notified of the detailed error via the
|on_fidl_error| method on the event handler.
## Thread safety
|Client| provides an easier to use API in exchange of a more restrictive
threading model:
- The provided |fdf_dispatcher_t| must be a [synchronized dispatcher][synchronized-dispatcher].
- The client must be bound on a task running on that dispatcher.
- The client must be destroyed on a task running on that dispatcher.
- FIDL method calls must be made from tasks running on that dispatcher.
- Responses are always delivered from dispatcher tasks, as are events.
The above rules are checked in debug builds at run-time. In short, the client
is local to its associated dispatcher.
Note that FIDL method calls must be synchronized with operations that consume
or mutate the |Client| itself:
- Assigning a new value to the |Client| variable.
- Moving the |Client| to a different location.
- Destroying the |Client|.
|Client| is suitable for systems with stronger sequential threading
guarantees. It is intended to be used as a local variable with fixed
lifetime, or as a member of a larger class where it is uniquely owned by
instances of that class. Destroying the |Client| is guaranteed to stop
message dispatch: since the client is destroyed on the dispatcher thread,
there is no opportunity of parallel callbacks to user code, and
use-after-free of user objects is naturally avoided during teardown.
See |SharedClient| for a client that supports binding and destroying on
arbitrary threads, at the expense of requiring two-phase shutdown.
[synchronized-dispatcher]:
https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/thread-safe-async#synchronized-dispatcher
Public Methods
template <typename AsyncEventHandler = fdf::AsyncEventHandler<Protocol>>
void Client<Protocol> (fdf::ClientEnd<Protocol> client_end, fdf_dispatcher_t * dispatcher, AsyncEventHandler * event_handler)
Create an initialized client which manages the binding of the client end of
a channel to a dispatcher, as if that client had been default-constructed
then later bound to that endpoint via |Bind|.
It is a logic error to use a dispatcher that is shutting down or already
shut down. Doing so will result in a panic.
If any other error occurs during initialization, the
|event_handler->on_fidl_error| handler will be invoked asynchronously with
the reason, if specified.
Defined at line 134 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
void Client<Protocol> ()
Create an uninitialized client. The client may then be bound to an endpoint
later via |Bind|.
Prefer using the constructor overload that binds the client to a channel
atomically during construction. Use this default constructor only when the
client must be constructed first before a channel could be obtained (for
example, if the client is an instance variable).
Defined at line 146 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
bool is_valid ()
Returns if the |Client| is initialized.
Defined at line 149 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
bool operator bool ()
Defined at line 150 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
void ~Client<Protocol> ()
The destructor of |Client| will initiate binding teardown.
When the client destructs:
- The channel will be closed.
- Pointers obtained via |get| will be invalidated.
- Binding teardown will happen, implying:
* In-progress calls will be forgotten. Async callbacks will be dropped.
Defined at line 159 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
void Client<Protocol> (Client<Protocol> && other)
|Client|s can be safely moved without affecting any in-flight FIDL
method calls. Note that calling methods on a client should be serialized
with respect to operations that consume the client, such as moving it or
destroying it.
Defined at line 165 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
Client<Protocol> & operator= (Client<Protocol> && other)
Defined at line 166 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
void Bind (fdf::ClientEnd<Protocol> client_end, fdf_dispatcher_t * dispatcher, fdf::AsyncEventHandler<Protocol> * event_handler)
Initializes the client by binding the |client_end| endpoint to the
dispatcher.
It is a logic error to invoke |Bind| on a dispatcher that is shutting down
or already shut down. Doing so will result in a panic.
When other errors occur during binding, the |event_handler->on_fidl_error|
handler will be asynchronously invoked with the reason, if specified.
It is not allowed to call |Bind| on an initialized client. To rebind a
|Client| to a different endpoint, simply replace the |Client|
variable with a new instance.
Defined at line 185 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
const NaturalClientImpl * operator-> ()
Returns the interface for making outgoing FIDL calls using natural objects.
The client must be initialized first.
If the binding has been torn down, calls on the interface return error with
status |ZX_ERR_CANCELED| and reason |fidl::Reason::kUnbind|.
Persisting this pointer to a local variable is discouraged, since that
results in unsafe borrows. Always prefer making calls directly via the
|Client| reference-counting type.
Defined at line 204 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
const NaturalClientImpl & operator* ()
Defined at line 205 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
auto wire ()
Returns the interface for making outgoing FIDL calls using wire objects.
The client must be initialized first.
If the binding has been torn down, calls on the interface return error with
status |ZX_ERR_CANCELED| and reason |fidl::Reason::kUnbind|.
Persisting this pointer to a local variable is discouraged, since that
results in unsafe borrows. Always prefer making calls directly via the
|Client| reference-counting type.
Defined at line 216 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h
fit::result<fidl::Error, fdf::ClientEnd<Protocol>> UnbindMaybeGetEndpoint ()
Attempts to disassociate the client object from its endpoint and stop
monitoring it for messages. After this call, subsequent operations will
fail with an unbound error.
If there are pending two-way async calls, the endpoint is closed and this
method will fail with |fidl::Reason::kPendingTwoWayCallPreventsUnbind|. The
caller needs to arrange things such that unbinding happens after any
replies to two-way calls.
If the endpoint was already closed due to an earlier error, that error will
be returned here.
Otherwise, returns the client endpoint.
Defined at line 234 of file ../../sdk/lib/fidl_driver/include/lib/fidl_driver/cpp/natural_client.h