Skip to content

Commit 92e52b8

Browse files
The same functions types work with boost and standalone asio
1 parent 4627de1 commit 92e52b8

9 files changed

Lines changed: 1827 additions & 81 deletions

File tree

Lines changed: 55 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//
21
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
32
//
43
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -7,80 +6,72 @@
76
// Official repository: https://github.com/cppalliance/capy
87
//
98

10-
#ifndef BOOST_CAPY_ASIO_AS_IO_AWAITABLE
11-
#define BOOST_CAPY_ASIO_AS_IO_AWAITABLE
12-
13-
#include <boost/capy/asio/detail/as_io_awaitable.hpp>
14-
#include <boost/capy/asio/detail/completion_handler.hpp>
15-
#include <boost/asio/async_result.hpp>
9+
#ifndef BOOST_CAPY_ASIO_DETAIL_AS_IO_AWAITABLE_HPP
10+
#define BOOST_CAPY_ASIO_DETAIL_AS_IO_AWAITABLE_HPP
1611

17-
#include <optional>
12+
#include <type_traits>
13+
#include <utility>
1814

19-
20-
template <typename... Ts>
21-
struct boost::asio::async_result<boost::capy::as_io_awaitable_t, void(Ts...)>
15+
namespace boost::capy
2216
{
23-
template<typename Initiation, typename... Args>
24-
struct awaitable_t
25-
{
26-
cancellation_signal signal;
27-
capy::detail::asio_immediate_executor_helper::completed_immediately_t ci;
2817

29-
struct cb
30-
{
31-
cancellation_signal &signal;
32-
cb(cancellation_signal &signal) : signal(signal) {}
33-
void operator()() {signal.emit(cancellation_type::terminal); }
34-
};
35-
std::optional<std::stop_callback<cb>> stopper;
36-
37-
bool await_ready() const {return false;}
3818

39-
void await_suspend(std::coroutine_handle<> h, const capy::io_env * env)
40-
{
41-
stopper.emplace(env->stop_token, signal);
42-
capy::detail::asio_coroutine_completion_handler<Ts...> ch(
43-
h, result_, env,
44-
signal.slot(),
45-
&ci);
46-
47-
std::apply(
48-
[&](auto ... args)
49-
{
50-
std::move(init_)(
51-
std::move(ch),
52-
std::move(args)...);
53-
},
54-
std::move(args_));
55-
56-
}
57-
58-
std::tuple<Ts...> await_resume() {return std::move(*result_); }
19+
struct as_io_awaitable_t
20+
{
21+
/// Default constructor.
22+
constexpr as_io_awaitable_t()
23+
{
24+
}
5925

26+
/// Adapts an executor to add the @c use_op_t completion token as the
27+
/// default.
28+
template <typename InnerExecutor>
29+
struct executor_with_default : InnerExecutor
30+
{
31+
/// Specify @c use_op_t as the default completion token type.
32+
typedef as_io_awaitable_t default_completion_token_type;
6033

61-
awaitable_t(Initiation init, std::tuple<Args...> args)
62-
: init_(std::move(init)), args_(std::move(args)) {}
63-
awaitable_t(awaitable_t && rhs) noexcept
64-
: init_(std::move(rhs.init_)), args_(std::move(rhs.args_)), result_(std::move(rhs.result_)) {}
65-
private:
66-
Initiation init_;
67-
std::tuple<Args...> args_;
68-
std::optional<std::tuple<Ts...>> result_;
69-
70-
};
34+
executor_with_default(const InnerExecutor& ex) noexcept
35+
: InnerExecutor(ex)
36+
{
37+
}
7138

72-
template <typename Initiation, typename RawCompletionToken, typename... Args>
73-
static auto initiate(Initiation&& initiation,
74-
RawCompletionToken&&, Args&&... args)
39+
/// Construct the adapted executor from the inner executor type.
40+
template <typename InnerExecutor1>
41+
executor_with_default(const InnerExecutor1& ex,
42+
typename std::enable_if<
43+
std::conditional<
44+
!std::is_same<InnerExecutor1, executor_with_default>::value,
45+
std::is_convertible<InnerExecutor1, InnerExecutor>,
46+
std::false_type
47+
>::type::value>::type = 0) noexcept
48+
: InnerExecutor(ex)
7549
{
76-
return awaitable_t<
77-
std::decay_t<Initiation>,
78-
std::decay_t<Args>...>(
79-
std::forward<Initiation>(initiation),
80-
std::make_tuple(std::forward<Args>(args)...));
8150
}
51+
};
52+
53+
/// Type alias to adapt an I/O object to use @c use_op_t as its
54+
/// default completion token type.
55+
template <typename T>
56+
using as_default_on_t = typename T::template rebind_executor<
57+
executor_with_default<typename T::executor_type> >::other;
58+
59+
/// Function helper to adapt an I/O object to use @c use_op_t as its
60+
/// default completion token type.
61+
template <typename T>
62+
static typename std::decay_t<T>::template rebind_executor<
63+
executor_with_default<typename std::decay_t<T>::executor_type>
64+
>::other
65+
as_default_on(T && object)
66+
{
67+
return typename std::decay_t<T>::template rebind_executor<
68+
executor_with_default<typename std::decay_t<T>::executor_type>
69+
>::other(std::forward<T>(object));
70+
}
8271
};
72+
constexpr as_io_awaitable_t as_io_awaitable;
8373

8474

85-
#endif
75+
}
8676

77+
#endif
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/capy
8+
//
9+
10+
#ifndef BOOST_CAPY_ASIO_AS_IO_AWAITABLE
11+
#define BOOST_CAPY_ASIO_AS_IO_AWAITABLE
12+
13+
#include <boost/capy/asio/detail/as_io_awaitable.hpp>
14+
#include <boost/capy/asio/detail/completion_handler.hpp>
15+
#include <boost/asio/async_result.hpp>
16+
17+
#include <optional>
18+
19+
20+
template <typename... Ts>
21+
struct boost::asio::async_result<boost::capy::as_io_awaitable_t, void(Ts...)>
22+
{
23+
template<typename Initiation, typename... Args>
24+
struct awaitable_t
25+
{
26+
cancellation_signal signal;
27+
capy::detail::asio_immediate_executor_helper::completed_immediately_t ci;
28+
29+
struct cb
30+
{
31+
cancellation_signal &signal;
32+
cb(cancellation_signal &signal) : signal(signal) {}
33+
void operator()() {signal.emit(cancellation_type::terminal); }
34+
};
35+
std::optional<std::stop_callback<cb>> stopper;
36+
37+
bool await_ready() const {return false;}
38+
39+
void await_suspend(std::coroutine_handle<> h, const capy::io_env * env)
40+
{
41+
stopper.emplace(env->stop_token, signal);
42+
capy::detail::asio_coroutine_completion_handler<Ts...> ch(
43+
h, result_, env,
44+
signal.slot(),
45+
&ci);
46+
47+
std::apply(
48+
[&](auto ... args)
49+
{
50+
std::move(init_)(
51+
std::move(ch),
52+
std::move(args)...);
53+
},
54+
std::move(args_));
55+
56+
}
57+
58+
std::tuple<Ts...> await_resume() {return std::move(*result_); }
59+
60+
61+
awaitable_t(Initiation init, std::tuple<Args...> args)
62+
: init_(std::move(init)), args_(std::move(args)) {}
63+
awaitable_t(awaitable_t && rhs) noexcept
64+
: init_(std::move(rhs.init_)), args_(std::move(rhs.args_)), result_(std::move(rhs.result_)) {}
65+
private:
66+
Initiation init_;
67+
std::tuple<Args...> args_;
68+
std::optional<std::tuple<Ts...>> result_;
69+
70+
};
71+
72+
template <typename Initiation, typename RawCompletionToken, typename... Args>
73+
static auto initiate(Initiation&& initiation,
74+
RawCompletionToken&&, Args&&... args)
75+
{
76+
return awaitable_t<
77+
std::decay_t<Initiation>,
78+
std::decay_t<Args>...>(
79+
std::forward<Initiation>(initiation),
80+
std::make_tuple(std::forward<Args>(args)...));
81+
}
82+
};
83+
84+
85+
#endif
86+

0 commit comments

Comments
 (0)