2
0
mirror of https://github.com/boostorg/asio.git synced 2026-01-27 18:42:07 +00:00
Commit Graph

1208 Commits

Author SHA1 Message Date
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
a8c7e7e8c1 Add missing #includes, destructor. 2021-07-04 13:03:06 +10:00
Christopher Kohlhoff
fb5311480d Change to co_spawn to dispatch first and only post if the coroutine did not context-switch. 2021-07-04 13:02:54 +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
1c3c80d778 Make experimental::parallel_group compatible with C++14. 2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
66b41bff1c Ensure all aligned allocations' sizes are a multiple of the alignment. 2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
5145c8f83d Add self-container-header checks for cancellation functionality. 2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
909f7ee6c0 Fix long lines. 2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
0c340c786a Add experimental::deferred completion token.
The experimental::deferred completion token takes a call to an
asynchronous operation's initiating function and turns it into a
function object that accepts a completion token. For example:

  auto deferred_op =
    timer.async_wait(
      boost::asio::experimental::deferred);
  ...
  std::move(deferred_op)(
      [](std::error_code ec){ ... });

or

  auto deferred_op =
    timer.async_wait(
      boost::asio::experimental::deferred);
  ...
  std::future<void> =
    std::move(deferred_op)(
      boost::asio::use_future);

The deferred token also supports chaining, to create simple
compositions:

  auto deferred_op =
    timer.async_wait(
      boost::asio::experimental::deferred(
        [&](std::error_code ec)
        {
          timer.expires_after(
              std::chrono::seconds(1));

          return timer.async_wait(
              boost::asio::experimental::deferred);
        });
  ...
  std::future<void> = std::move(deferred_op)(boost::asio::use_future);
2021-07-01 10:52:01 +10:00
Christopher Kohlhoff
b899f98566 Add experimental::prepend completion token adapter.
The prepend completion token adapter can be used to pass additional
before the existing completion handler arguments. For example:

  timer.async_wait(
      boost::asio::experimental::prepend(
        [](int i, std::error_code ec)
        {
          // ...
        },
      42)
    );

  std::future<std::tuple<int, std::error_code>> f = timer.async_wait(
      boost::asio::experimental::prepend(
        boost::asio::use_future,
        42
      )
    );
2021-07-01 10:51:52 +10:00
Christopher Kohlhoff
560446b93e Fix return type deduction in experimental::append. 2021-07-01 10:13:48 +10:00
Christopher Kohlhoff
d18260d8e0 Initial implementation of parallel_group. 2021-07-01 10:12:53 +10:00
Christopher Kohlhoff
4919e61897 Support multiple ref-qualified completion signatures with experimental::as_tuple. 2021-06-28 10:19:13 +10:00
Christopher Kohlhoff
36bde1abad Support ref-qualified completion signatures with redirect_error. 2021-06-28 10:19:05 +10:00
Christopher Kohlhoff
efcf51bb9d Add support for ref-qualified completion signatures. 2021-06-28 10:18:52 +10:00
Christopher Kohlhoff
9d9543d79c Add support for completion tokens with multiple signatures. 2021-06-28 10:18:37 +10:00
Christopher Kohlhoff
8164518ace Add experimental::append completion token adapter.
The append completion token adapter can be used to pass additional
completion handler arguments. For example:

  timer.async_wait(
      boost::asio::experimental::append(
        [](std::error_code ec, int i)
        {
          // ...
        },
      42)
    );

  std::future<int> f = timer.async_wait(
      boost::asio::experimental::append(
        asio::use_future,
        42
      )
    );
2021-06-28 10:18:12 +10:00
Christopher Kohlhoff
543aa4e1c9 Add cancellation support to select_reactor. 2021-06-28 10:12:34 +10:00
Christopher Kohlhoff
d953c551e3 Add cancellation_slot support to ssl::stream async operations. 2021-06-28 10:12:18 +10:00
Christopher Kohlhoff
34f0a08c81 Add cancellation_slot support to async_write_at. 2021-06-28 10:12:10 +10:00
Christopher Kohlhoff
9bbf82f17b Add cancellation_slot support to async_read_at. 2021-06-28 10:12:02 +10:00
Christopher Kohlhoff
c8f734aa84 Add cancellation_slot support to async_read_until. 2021-06-28 10:11:54 +10:00
Christopher Kohlhoff
4467d996b9 Add cancellation_slot support to async_compose. 2021-06-28 10:11:36 +10:00
Christopher Kohlhoff
81ff304666 Add cancellation_slot support to async_connect. 2021-06-28 10:11:28 +10:00
Christopher Kohlhoff
8a697744bc Add cancellation_slot support to async_write. 2021-06-28 10:11:20 +10:00
Christopher Kohlhoff
210a325667 Add cancellation_slot support to async_read. 2021-06-28 10:11:06 +10:00
Christopher Kohlhoff
c6a83c0344 Add detail::base_from_cancellation_state helper class. 2021-06-28 10:10:57 +10:00
Christopher Kohlhoff
ca40143009 Add cancellation_slot support to awaitable<>-based coroutines. 2021-06-28 10:10:40 +10:00
Christopher Kohlhoff
4e9f42b73f Add cancellation_state. 2021-06-28 10:10:27 +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
e4f7cd3238 Add cancellation support to reactor-based sockets. 2021-06-28 10:09:20 +10:00
Christopher Kohlhoff
e16a4a1eaf Add cancellation_slot support to posix descriptors. 2021-06-28 10:09:12 +10:00
Christopher Kohlhoff
507ec5408e Add cancellation_slot support to timers. 2021-06-28 10:08:58 +10:00
Christopher Kohlhoff
6dc719f036 Add associated_cancellation_slot associator. 2021-06-28 10:08:23 +10:00
Christopher Kohlhoff
3521da0834 Add cancellation_signal and cancellation_slot. 2021-06-28 10:08:05 +10:00
Christopher Kohlhoff
23c2400f99 Add cancellation_type enum. 2021-06-28 10:07:51 +10:00
Christopher Kohlhoff
cbaf9ce318 The aligned_alloc function requires that size be a multiple of align. 2021-06-28 10:07:33 +10:00
Christopher Kohlhoff
5c006c4fea Fix detection of MSVC. 2021-06-28 10:07:24 +10:00
Christopher Kohlhoff
7d0397b0b3 Use std::aligned_alloc rather than operator new. 2021-06-28 10:07:15 +10:00
Christopher Kohlhoff
97d8a5686e Enable additional optimisations for any_executor and any_io_executor in detail::handler_work<>. 2021-06-11 19:08:46 +10:00
Christopher Kohlhoff
059c11aae5 Check feature-test macro for aligned new. 2021-06-11 19:08:35 +10:00
Christopher Kohlhoff
3ba403d306 Invoke completion handlers as rvalue references. 2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
aa311e118c Add experimental::as_tuple completion token adapter.
The as_tuple completion token adapter can be used to specify that the
completion handler arguments should be combined into a single tuple
argument.

The as_tuple adapter may be used in conjunction with use_awaitable and
structured bindings as follows:

    auto [e, n] = co_await socket.async_read_some(
        asio::buffer(data), as_tuple(use_awaitable));

Alternatively, it may be used as a default completion token like so:

    using default_token = as_tuple_t<use_awaitable_t<>>;
    using tcp_socket = default_token::as_default_on_t<tcp::socket>;
    // ...
    awaitable<void> do_read(tcp_socket socket)
    {
      // ...
      auto [e, n] = co_await socket.async_read_some(asio::buffer(data));
      // ...
    }
2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
059c40e935 Add initiate-based completion token support to bind_executor. 2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
99114f2b5a Use associator trait in buffered_write_stream implementation. 2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
bb6dd90ac4 Use associator trait in buffered_read_stream implementation. 2021-06-05 17:43:31 +10:00
Christopher Kohlhoff
477d31f4d0 Use associator trait in spawn implementation. 2021-06-05 17:43:31 +10:00