[/
    Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    Official repository: https://github.com/boostorg/beast
]

[section:echo 回显 __示例__]

该示例用于开发名为 [*echo] 的启动函数。该操作从流中读取数据，直到遇到第一个换行符为止，然后将读取的内容（包含该换行符）写回流中。实现步骤如下：首先定义输入参数与返回结果，然后声明启动函数。该回显操作的输入参数仅为流对象与完成令牌，返回结果为错误码。该错误码通常包含在所有完成处理器的签名中。

[example_core_echo_op_2]

完成函数声明后，我们再对该函数的实现部分进行定义。实现过程中需要满足以下几个目标：对输入参数执行静态类型检查，按照 __N3747__ 规范设定返回值类型，同时构造一个带有状态的中间完成处理器并调用该处理器，以此启动组合操作。

发起函数包含几个相对简单的部分：定制返回值类型、静态类型检查、使用辅助工具构建返回值类型，以及创建并启动 `echo_op` 组合操作对象。

实现策略是让组合对象满足完成处理器的要求：一方面要支持移动语义，另一方面要使其可调用，这样它就能作为其发起的异步操作的后续回调来使用。我们不使用 `std::bind` 或 `boost::bind`，因为它们会丢失类型信息，从而破坏关联器。相反，我们会直接把 `std::move(*this)` 作为完成处理器参数，传递给所发起的每个异步操作。为确保移动操作能正确工作，需要注意在移动发生之后，不能再访问任何数据成员。以下是该组合操作的完整实现：

[example_core_echo_op_3]

当编写组合操作时，需要避免以下几种常见错误：

* 对最终处理器进行类型擦除，该操作会导致未定义行为。

* 调用异步发起函数后忘记包含 return 语句
  initiating function.

* 意外调用同步函数。通常情况下，
  operations should not block for long periods of time, since this
  ties up a thread running on the __io_context__.

* 忘记提供 `executor_type` 和 `get_executor` 成员（为组合操作提供）。
  composed operation. This will cause undefined behavior. For example,
  if someone  calls the initiating function with a strand-wrapped
  function object, and there is more than thread running on the
  __io_context__, the underlying stream may be accessed in a fashion
  that violates safety guarantees. Beast provides class templates
  to take care of this boilerplate for you.

* 忘记创建 __executor_work_guard__ 对象（使用执行器来创建）。
  type of executor returned by the stream's `get_executor` member function.

对于立即完成的操作（即无需调用异步发起函数即可完成的操作），
  intermediate initiating function), forgetting to use __post__ to
  invoke the final handler. This breaks the following initiating
  function guarantee: ['Regardless of whether the asynchronous operation
  completes immediately or not, the handler will not be invoked from
  within this function. Invocation of the handler will be performed
  in a manner equivalent to using __post__]. The function
  __bind_handler__ is provided for this purpose.

该示例的完整可运行代码参见 [path_link example/echo-op/echo_op.cpp echo_op.cpp]。

[endsect]
