2
0
mirror of https://github.com/boostorg/asio.git synced 2026-02-23 14:02:13 +00:00
Commit Graph

252 Commits

Author SHA1 Message Date
Christopher Kohlhoff
4ca5e6a13a Make promise test more resistant to a heavily loaded test system. 2021-07-05 18:45:03 +10:00
Christopher Kohlhoff
769dc0e149 Add this_coro::throw_if_cancelled.
By default, awaitable<>-based coroutines now throw an exception if they
have been previously cancelled, and then try to perform a co_await
against another awaitable<>.

To disable this behaviour for the current awaitable<>-based "thread",
perform:

    co_await boost::asio::this_coro::throw_if_error(false);

It is then the responsibility of the coroutine implementation to ensure
that it checks the cancellation state of the coroutine manually, by
doing something like:

    auto cs = boost::asio::this_coro::cancellation_state;
    // ...
    if (cs.cancelled() != cancellation_type::none)
    {
      // ... handle cancellation ...
    }
2021-07-04 13:10:27 +10:00
Christopher Kohlhoff
d2ab7b7669 Fix yield input in experimental::coro. 2021-07-04 13:10:27 +10:00
Christopher Kohlhoff
01ca2be880 Ensure experimental::deferred header is self-contained. 2021-07-04 13:10:27 +10:00
Christopher Kohlhoff
f486b43c16 Add operator&& and operator|| for awaitable<>.
The logical operators || and && have been overloaded for awaitable<>, to
allow coroutines to be trivially awaited in parallel.

When awaited using &&, the await expression waits until both operations
have completed successfully. As a "short-circuit" evaluation, if one
operation fails with an exception, the other is immediately cancelled.
For example:

    std::tuple<std::size_t, std::size_t> results =
      co_await (
        async_read(socket, input_buffer, use_awaitable)
          && async_write(socket, output_buffer, use_awaitable)
      );

When awaited using ||, the await expression waits until either operation
succceeds. As a "short-circuit" evaluation, if one operation succeeds
without throwing an exception, the other is immediately cancelled. For
example:

    std::variant<std::size_t, std::monostate> results =
      co_await (
        async_read(socket, input_buffer, use_awaitable)
          || timer.async_wait(use_awaitable)
      );

The operators may be enabled by adding the #include:

    #include <asio/experimental/awaitable_operators.hpp>

and then bringing the contents of the experimental::awaitable_operators
namespace into scope:

    using namespace boost::asio::experimental::awaitable_operators;
2021-07-04 13:05:46 +10:00
Christopher Kohlhoff
9b3fc2ef83 Add move assignment to ssl::stream<>. 2021-07-02 12:29:57 +10:00
klemens-morgenstern
ecca8406c0 Added experimental::coro class template.
The coro type is a C++20 coroutine primitive for resumable functions,
with the ability to combine both asynchronous waiting (co_await) and
yielding (co_yield) into a single, stateful control flow. For example:

    #include <boostasio.hpp>
    #include <boostasio/experimental/coro.hpp>

    using boost::asio::ip::tcp;

    boost::asio::experimental::coro<std::string> reader(tcp::socket& sock)
    {
      std::string buf;
      while (sock.is_open())
      {
        std::size_t n = co_await boost::asio::async_read_until(
            sock, boost::asio::dynamic_buffer(buf), '\n',
            boost::asio::experimental::use_coro);
        co_yield buf.substr(0, n);
        buf.erase(0, n);
      }
    }

    boost::asio::awaitable<void> consumer(tcp::socket sock)
    {
      auto r = reader(sock);
      auto msg1 = co_await r.async_resume(boost::asio::use_awaitable);
      std::cout << "Message 1: " << msg1.value_or("\n");
      auto msg2 = co_await r.async_resume(boost::asio::use_awaitable);
      std::cout << "Message 2: " << msg2.value_or("\n");
    }

    boost::asio::awaitable<void> listen(tcp::acceptor& acceptor)
    {
      for (;;)
      {
        co_spawn(
            acceptor.get_executor(),
            consumer(co_await acceptor.async_accept(boost::asio::use_awaitable)),
            boost::asio::detached);
      }
    }

    int main()
    {
      boost::asio::io_context ctx;
      tcp::acceptor acceptor(ctx, {tcp::v4(), 54321});
      co_spawn(ctx, listen(acceptor), boost::asio::detached);
      ctx.run();
    }
2021-07-01 21:34:51 +10:00
klemens-morgenstern
03ba758437 Added experimental::promise.
The experimental::promise type allows eager execution and
synchronisation of async operations.

    auto promise = async_read(
        stream, asio::buffer(my_buffer),
        asio::experimental::use_promise);

    ... do other stuff while the read is going on ...

    promise.async_wait( // completion the operation
        [](error_code ec, std::size_t bytes_read)
        {
          ...
        });

Promises can be safely disregarded if the result is no longer required.

Different operations can be combined to either wait for all to complete
or for one to complete (and cancel the rest). For example, to wait for
one to complete:

    auto timeout_promise =
      timer.async_wait(
        asio::experimental::use_promise);

    auto read_promise = async_read(
        stream, asio::buffer(my_buffer),
        asio::experimental::use_promise);

    auto promise =
      asio::experimental::promise<>::race(
        timeout_promise, read_promise);

    promise.async_wait(
        [](std::variant<error_code, std::tuple<error_code, std::size_t>> v)
        {
          if (v.index() == 0) {} //timed out
          else if (v.index() == 1) // completed in time
        });

or to wait for all to complete:

    auto write_promise = async_write(
        stream, asio::buffer(my_write_buffer),
        asio::experimental::use_promise);

    auto read_promise = async_read(
        stream, asio::buffer(my_buffer),
        asio::experimental::use_promise);

    auto promise =
      asio::experimental::promise<>::all(
        write_promise, read_promise);

    promise.async_wait(
        [](std::tuple<error_code, std::size_t> write_result,
          std::tuple<error_code, std::size_t> read_result)
        {
        });
2021-07-01 15:40:28 +10:00
Christopher Kohlhoff
5145c8f83d Add self-container-header checks for cancellation functionality. 2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
4467d996b9 Add cancellation_slot support to async_compose. 2021-06-28 10:11:36 +10:00
Christopher Kohlhoff
f8b37f0c90 Add bind_cancellation_slot function and cancellation_slot_binder adapter. 2021-06-28 10:10:07 +10:00
Christopher Kohlhoff
059c40e935 Add initiate-based completion token support to bind_executor. 2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
0b0b904883 Add std::hash specialisations for ip::basic_endpoint<>. 2021-02-25 08:37:47 +11:00
Christopher Kohlhoff
eed38fbe97 Add std::hash specialisations for IP addresses. 2021-02-25 08:35:32 +11:00
Christopher Kohlhoff
723982b867 Update copyright notices. 2021-02-25 08:29:05 +11:00
Christopher Kohlhoff
fc4546c8d3 Fix thread_pool test to work with BOOST_ASIO_NO_TYPEID (i.e. no RTTI). 2020-11-02 14:03:09 +11:00
Christopher Kohlhoff
517e25cdcb Ensure concept-related traits work with void. 2020-07-31 18:47:51 +10:00
Christopher Kohlhoff
543c453423 Make blocking_t::always_t::is_preferable false as per specification. 2020-07-28 22:16:24 +10:00
Christopher Kohlhoff
95da815545 Add standard executor support to windows::overlapped_ptr. 2020-07-23 21:54:16 +10:00
Christopher Kohlhoff
04e1412d68 Fix uninitialised variable. 2020-07-23 21:51:38 +10:00
Christopher Kohlhoff
d497ba96c6 Rename the customisation point traits X_result_type to X_result.
For consistency with std::invoke_result, drop the _type suffix from all
traits that deduce the result type of a customisation point expression.
2020-07-06 23:33:14 +10:00
Christopher Kohlhoff
253f0130d3 Test any_executor construction and assignment with large targets. 2020-07-06 00:46:54 +10:00
Christopher Kohlhoff
98107ffb09 Use the execution::execute() customisation point for any_executor's target. 2020-07-04 14:46:54 +10:00
Christopher Kohlhoff
5a69376da9 Add missing adapter support to execution::bulk_execute() customisation point. 2020-07-04 01:24:01 +10:00
Christopher Kohlhoff
2e9621e8ba Add missing member and non-member swap to any_executor. 2020-07-04 01:23:11 +10:00
Christopher Kohlhoff
9af6e05eb5 Add missing equality/inequality operators to any_executor. 2020-07-04 01:22:56 +10:00
Christopher Kohlhoff
8f755ac905 Add missing any_executor constructor/assignment overloads. 2020-07-03 14:45:46 +10:00
Christopher Kohlhoff
b840adb353 Add bulk_execute() to thread_pool executor. 2020-07-02 00:24:34 +10:00
Christopher Kohlhoff
38514aca66 Add execution::bulk_execute customisation point object. 2020-07-02 00:23:04 +10:00
Christopher Kohlhoff
9a1f89d748 Add adapter for execution::blocking_adaptation_t::allowed_t. 2020-07-02 00:17:51 +10:00
Christopher Kohlhoff
3c8097af00 Add execution::typed_sender concept and execution::is_typed_sender trait. 2020-07-01 13:58:58 +10:00
Christopher Kohlhoff
00248b6739 Add scheduler and sender support to thread_pool.
The thread_pool::basic_executor_type class template is used as the
implementation for both the scheduler and sender types.
2020-06-30 22:39:08 +10:00
Christopher Kohlhoff
19c06f6931 Add execution::scheduler concept and execution::is_scheduler trait. 2020-06-30 22:39:08 +10:00
Christopher Kohlhoff
e93522cf35 Add execution::executor_index trait. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
49a3e6c628 Add execution::executor_shape trait. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
8081d7ee9d Add execution::schedule() customisation point object. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
75b2c02896 Add execution::execute() support for adapting senders. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
76789c2324 Add execution::submit() customisation point object. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
c27c6f2af8 Change execution::sender_traits to recognise executors as senders. 2020-06-30 22:38:09 +10:00
Christopher Kohlhoff
7edcde3d97 Add execution::connect() customisation point object. 2020-06-30 22:15:35 +10:00
Christopher Kohlhoff
63d35468c0 Add execution::sender concepts and traits.
This change adds the concept:

  * execution::sender

the traits:

  * execution::sender_traits

and the tag type:

  * execution::sender_base

It also adds the following traits that correspond to the concepts:

  * execution::is_sender
2020-06-30 22:09:19 +10:00
Christopher Kohlhoff
4569c722ec Add execution::operation_state concept and execution::is_operation_state trait. 2020-06-30 22:08:19 +10:00
Christopher Kohlhoff
ca3a44ea3c Add execution::start() customisation point object. 2020-06-30 22:07:21 +10:00
Christopher Kohlhoff
36a811264d Add execution::executor_of concept and execution::is_executor trait. 2020-06-30 22:06:22 +10:00
Christopher Kohlhoff
4d8e791a8f Add execution::receiver concepts and traits.
This change adds the concepts:

  * execution::receiver
  * execution::receiver_of

and the trait:

  * execution::is_nothrow_receiver_of

It also adds the following traits that correspond to the concepts:

  * execution::is_receiver
  * execution::is_receiver_of
2020-06-30 22:02:21 +10:00
Christopher Kohlhoff
b68f15843c Add execution::set_value() customisation point object. 2020-06-30 21:55:37 +10:00
Christopher Kohlhoff
bd5acb1d51 Add execution::set_done() customisation point object. 2020-06-30 21:54:13 +10:00
Christopher Kohlhoff
3a22a4fb7b Add execution::set_error() customisation point object. 2020-06-30 21:52:51 +10:00
Christopher Kohlhoff
fcd09b9c81 Build execution tests. 2020-06-26 16:42:45 +10:00
Christopher Kohlhoff
3fc1f87a2b Add standard executor support to strand<>. 2020-06-23 11:08:25 +10:00