1  
//
1  
//
2  
// Copyright (c) 2026 Michael Vandeberg
2  
// Copyright (c) 2026 Michael Vandeberg
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/corosio
7  
// Official repository: https://github.com/cppalliance/corosio
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_COROSIO_DETAIL_OP_BASE_HPP
10  
#ifndef BOOST_COROSIO_DETAIL_OP_BASE_HPP
11  
#define BOOST_COROSIO_DETAIL_OP_BASE_HPP
11  
#define BOOST_COROSIO_DETAIL_OP_BASE_HPP
12  

12  

13  
#include <boost/capy/io_result.hpp>
13  
#include <boost/capy/io_result.hpp>
14  
#include <boost/capy/ex/executor_ref.hpp>
14  
#include <boost/capy/ex/executor_ref.hpp>
15  
#include <boost/capy/ex/io_env.hpp>
15  
#include <boost/capy/ex/io_env.hpp>
16  

16  

17  
#include <coroutine>
17  
#include <coroutine>
18  
#include <cstddef>
18  
#include <cstddef>
19  
#include <stop_token>
19  
#include <stop_token>
20  
#include <system_error>
20  
#include <system_error>
21  

21  

22  
namespace boost::corosio::detail {
22  
namespace boost::corosio::detail {
23  

23  

24  
/* CRTP base for awaitables that return io_result<std::size_t>.
24  
/* CRTP base for awaitables that return io_result<std::size_t>.
25  

25  

26  
   Derived classes must provide:
26  
   Derived classes must provide:
27  

27  

28  
     std::coroutine_handle<> dispatch(
28  
     std::coroutine_handle<> dispatch(
29  
         std::coroutine_handle<> h,
29  
         std::coroutine_handle<> h,
30  
         capy::executor_ref ex) const;
30  
         capy::executor_ref ex) const;
31  

31  

32  
   which forwards to the backend implementation method, passing
32  
   which forwards to the backend implementation method, passing
33  
   token_, &ec_, and &bytes_ as the cancellation/output parameters.
33  
   token_, &ec_, and &bytes_ as the cancellation/output parameters.
34  
*/
34  
*/
35  
template<class Derived>
35  
template<class Derived>
36  
class bytes_op_base
36  
class bytes_op_base
37  
{
37  
{
38  
    friend Derived;
38  
    friend Derived;
39  
    bytes_op_base() = default;
39  
    bytes_op_base() = default;
40  

40  

41  
public:
41  
public:
42  
    std::stop_token token_;
42  
    std::stop_token token_;
43  
    mutable std::error_code ec_;
43  
    mutable std::error_code ec_;
44  
    mutable std::size_t bytes_ = 0;
44  
    mutable std::size_t bytes_ = 0;
45  

45  

46  
    bool await_ready() const noexcept
46  
    bool await_ready() const noexcept
47  
    {
47  
    {
48  
        return token_.stop_requested();
48  
        return token_.stop_requested();
49  
    }
49  
    }
50  

50  

51  
    capy::io_result<std::size_t> await_resume() const noexcept
51  
    capy::io_result<std::size_t> await_resume() const noexcept
52  
    {
52  
    {
53  
        if (token_.stop_requested())
53  
        if (token_.stop_requested())
54  
            return {make_error_code(std::errc::operation_canceled), 0};
54  
            return {make_error_code(std::errc::operation_canceled), 0};
55  
        return {ec_, bytes_};
55  
        return {ec_, bytes_};
56  
    }
56  
    }
57  

57  

58  
    auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
58  
    auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
59  
        -> std::coroutine_handle<>
59  
        -> std::coroutine_handle<>
60  
    {
60  
    {
61  
        token_ = env->stop_token;
61  
        token_ = env->stop_token;
62  
        return static_cast<Derived const*>(this)->dispatch(
62  
        return static_cast<Derived const*>(this)->dispatch(
63  
            h, env->executor);
63  
            h, env->executor);
64  
    }
64  
    }
65  
};
65  
};
66  

66  

67  
/* CRTP base for awaitables that return io_result<>.
67  
/* CRTP base for awaitables that return io_result<>.
68  

68  

69  
   Derived classes must provide:
69  
   Derived classes must provide:
70  

70  

71  
     std::coroutine_handle<> dispatch(
71  
     std::coroutine_handle<> dispatch(
72  
         std::coroutine_handle<> h,
72  
         std::coroutine_handle<> h,
73  
         capy::executor_ref ex) const;
73  
         capy::executor_ref ex) const;
74  

74  

75  
   which forwards to the backend implementation method, passing
75  
   which forwards to the backend implementation method, passing
76  
   token_ and &ec_ as the cancellation/output parameters.
76  
   token_ and &ec_ as the cancellation/output parameters.
77  
*/
77  
*/
78  
template<class Derived>
78  
template<class Derived>
79  
class void_op_base
79  
class void_op_base
80  
{
80  
{
81  
    friend Derived;
81  
    friend Derived;
82  
    void_op_base() = default;
82  
    void_op_base() = default;
83  

83  

84  
public:
84  
public:
85  
    std::stop_token token_;
85  
    std::stop_token token_;
86  
    mutable std::error_code ec_;
86  
    mutable std::error_code ec_;
87  

87  

88  
    bool await_ready() const noexcept
88  
    bool await_ready() const noexcept
89  
    {
89  
    {
90  
        return token_.stop_requested();
90  
        return token_.stop_requested();
91  
    }
91  
    }
92  

92  

93  
    capy::io_result<> await_resume() const noexcept
93  
    capy::io_result<> await_resume() const noexcept
94  
    {
94  
    {
95  
        if (token_.stop_requested())
95  
        if (token_.stop_requested())
96  
            return {make_error_code(std::errc::operation_canceled)};
96  
            return {make_error_code(std::errc::operation_canceled)};
97  
        return {ec_};
97  
        return {ec_};
98  
    }
98  
    }
99  

99  

100  
    auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
100  
    auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
101  
        -> std::coroutine_handle<>
101  
        -> std::coroutine_handle<>
102  
    {
102  
    {
103  
        token_ = env->stop_token;
103  
        token_ = env->stop_token;
104  
        return static_cast<Derived const*>(this)->dispatch(
104  
        return static_cast<Derived const*>(this)->dispatch(
105  
            h, env->executor);
105  
            h, env->executor);
106  
    }
106  
    }
107  
};
107  
};
108  

108  

109  
} // namespace boost::corosio::detail
109  
} // namespace boost::corosio::detail
110  

110  

111  
#endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP
111  
#endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP