## Prerequisites

This tutorial builds on the [getting started tutorials](https://fuchsia.dev/docs/development/languages/fidl/tutorials/cpp/README).

## Overview

The full example code for this tutorial is located at
[//examples/fidl/cpp/server_async_completer](https://cs.opensource.google/fuchsia/fuchsia/+/main:/examples/fidl/cpp/server_async_completer).

In the `Echo` implementation from the initial [server tutorial](https://fuchsia.dev/docs/development/languages/fidl/tutorials/cpp/basics/server), the
server code responded to `EchoString` requests using the completer:

    void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
      // Call |Reply| to reply synchronously with the request value.
      completer.Reply({{.response = request.value()}});
    }

Notice that the type of the completer ends with `::Sync`. Sync completers must
be used before the handler returns. Enforcing this allows optimizations since
the bookkeeping metadata for making a reply can be stack allocated.

## Respond asynchronously

In many cases responding synchronously is infeasible. For example, the reply may
need results from other asynchronous calls. To respond asynchronously, we must
obtain an async completer from the sync completer, using `ToAsync`:

    EchoStringCompleter::Async async_completer = completer.ToAsync();

The resulting `async_completer` exposes the same API as `completer`, but can be
moved away to be used at a later time.

In the example code, the server makes the reply inside a delayed task, emulating
a scenario where the server must execute a long running task before sending a
response:

    void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
      async::PostDelayedTask(
          dispatcher_,
          [value = request.value(), completer = completer.ToAsync()]() mutable {
            completer.Reply({{.response = value}});
          },
          zx::duration(ZX_SEC(1)));
    }

The server won't start handling any new requests until returning from the
current handler method. After returning from `EchoString`, the server will
monitor the endpoint for new FIDL messages, while the reply is scheduled one
second into the future. This means if the client sent multiple `EchoString`
requests in quick succession, we may have just as many concurrent async delayed
tasks in flight.

> [!NOTE]
> **Note:** if the async completer is captured by a lambda function, the lambda must be marked **mutable**, because making a reply using the completer mutates it such that duplicate replies will panic.

### Respond asynchronously in servers speaking wire domain objects

You would use the same `ToAsync` operation when the server speaks
[wire domain objects](https://fuchsia.dev/docs/development/languages/fidl/tutorials/cpp/basics/domain-objects#using-wire), but pay extra attention to object lifetimes.
In particular, the request views provided to method handlers do not own the
request message. If an asynchronous task needs to use the request parameters
after the `EchoString` method returns, we need to copy relevant fields to an
owned type:

    class EchoImpl : public fidl::WireServer<fuchsia_examples::Echo> {
     public:
      void EchoString(EchoStringRequestView request, EchoStringCompleter::Sync& completer) override {
        // Copy the contents of |request->value| (a fidl::StringView) to a string.
        std::string value_owned{request->value.get()};
        async::PostDelayedTask(
            dispatcher_,
            [value = value_owned, completer = completer.ToAsync()]() mutable {
              completer.Reply(fidl::StringView::FromExternal(value));
            },
            zx::duration(ZX_SEC(1)));
      }

      // ...
    };

For further information on the memory ownership, refer to
[Memory ownership of wire domain objects](https://fuchsia.dev/docs/development/languages/fidl/tutorials/cpp/topics/wire-memory-ownership).

## Run the example

In order for the client and server to communicate using the `Echo` protocol,
component framework must route the `fuchsia.examples.Echo` capability from the
server to the client. For this tutorial, a


[](https://fuchsia.dev/docs/glossary#realm)


component is
provided to declare the appropriate capabilities and routes.

> [!NOTE]
> **Note:** You can explore the full source for the realm component at [`//examples/fidl/echo-realm`](https://cs.opensource.google/fuchsia/fuchsia/+/main:/examples/fidl/echo-realm)

1. Configure your build to include the provided package that includes the
   echo realm, server, and client:

       fx set core.x64 --with //examples/fidl/cpp/server_async_completer:echo-cpp-async

2. Build the Fuchsia image:

       fx build

3. Run the `echo_realm` component. This creates the client and server component
   instances and routes the capabilities:

       ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-cpp-async#meta/echo_realm.cm

4. Start the `echo_client` instance:

       ffx component start /core/ffx-laboratory:echo_realm/echo_client

The server component starts when the client attempts to connect to the `Echo`
protocol. You should see output similar to the following in the device logs
(`ffx log`). The leftmost column is the timestamp:

    [21611.962][echo_server][I] Running C++ echo server with natural types
    [21611.965][echo_server][I] Incoming connection for fuchsia.examples.Echo
    [21612.998][echo_client][I] (Natural types) got response: hello
    [21613.999][echo_client][I] (Natural types) got response: hello
    [21614.000][echo_client][I] (Natural types) got event: hello
    [21615.002][echo_client][I] (Wire types) got response: hello
    [21615.003][echo_client][I] (Natural types) got event: hello
    [21615.003][echo_server][I] Client disconnected

Note that it takes about one second between
`Incoming connection for fuchsia.examples.Echo` and
`(Natural types) got response: hello`, because the server is programmed to
asynchronously delay the response by one second.

Terminate the realm component to stop execution and clean up the component
instances:

    ffx component destroy /core/ffx-laboratory:echo_realm

[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/development/languages/fidl/tutorials/cpp/topics/async-completer.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/development/languages/fidl/tutorials/cpp/topics/async-completer.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/development/languages/fidl/tutorials/cpp/topics/async-completer.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/development/languages/fidl/tutorials/cpp/topics/async-completer.md "Edit the source code of this page")