TLA Line data Source code
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_CONTINUATION_HPP
11 : #define BOOST_CAPY_ASIO_CONTINUATION_HPP
12 :
13 : #include <boost/capy/continuation.hpp>
14 : #include <boost/capy/concept/executor.hpp>
15 :
16 : #include <memory>
17 :
18 : namespace boost::capy
19 : {
20 :
21 : namespace detail
22 : {
23 :
24 : template<typename Allocator>
25 : struct continuation_handle_promise_base_
26 : {
27 : using alloc_t = std::allocator_traits<Allocator>
28 : ::template rebind_alloc<char>;
29 :
30 : template<typename Func>
31 HIT 5 : void * operator new(std::size_t n, Func &, Allocator &allocator_)
32 : {
33 5 : alloc_t alloc(allocator_);
34 5 : std::size_t m = n;
35 5 : if (n % alignof(alloc_t) > 0)
36 MIS 0 : m += alignof(alloc_t) - (n % alignof(alloc_t));
37 :
38 HIT 5 : char * mem = alloc.allocate(m + sizeof(alloc));
39 :
40 5 : new (mem + m) alloc_t(std::move(alloc));
41 5 : return mem;
42 : }
43 :
44 5 : void operator delete(void * p, std::size_t n)
45 : {
46 5 : std::size_t m = n;
47 5 : if (n % alignof(alloc_t) > 0)
48 MIS 0 : m += alignof(alloc_t) - (n % alignof(alloc_t));
49 :
50 HIT 5 : auto * a = reinterpret_cast<alloc_t*>(static_cast<char*>(p) + m);
51 :
52 5 : alloc_t alloc(std::move(*a));
53 5 : a->~alloc_t();
54 :
55 5 : alloc.deallocate(static_cast<char*>(p), n);
56 5 : }
57 : };
58 :
59 :
60 : template<>
61 : struct continuation_handle_promise_base_<std::allocator<void>>
62 : {
63 : };
64 :
65 : template<typename Allocator>
66 : struct continuation_handle_promise_type
67 : : continuation_handle_promise_base_<Allocator>
68 : {
69 :
70 : struct initial_aw_t
71 : {
72 11 : bool await_ready() const {return false;}
73 11 : void await_suspend(
74 : std::coroutine_handle<continuation_handle_promise_type<Allocator>> h)
75 : {
76 11 : auto & c = h.promise().cont;
77 11 : c.h = h;
78 11 : c.next = nullptr;
79 11 : }
80 11 : void await_resume() {}
81 : };
82 :
83 11 : initial_aw_t initial_suspend() const noexcept
84 : {
85 11 : return initial_aw_t{};
86 : }
87 MIS 0 : std::suspend_never final_suspend() const noexcept {return {};}
88 :
89 : template<typename Function>
90 HIT 11 : auto yield_value(Function & func)
91 : {
92 : struct yielder
93 : {
94 : Function func;
95 :
96 11 : bool await_ready() const {return false;}
97 11 : void await_suspend(std::coroutine_handle<> h)
98 : {
99 11 : auto f = std::move(func);
100 11 : h.destroy();
101 :
102 : #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 14)
103 : #pragma GCC diagnostic push
104 : #pragma GCC diagnostic ignored "-Warray-bounds"
105 : #endif
106 :
107 11 : std::move(f)();
108 :
109 : #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 14)
110 : #pragma GCC diagnostic pop
111 : #endif
112 :
113 11 : }
114 MIS 0 : void await_resume() {}
115 : };
116 :
117 HIT 11 : return yielder{std::move(func)};
118 : }
119 :
120 MIS 0 : void unhandled_exception() { throw; }
121 0 : void return_void() {}
122 :
123 : continuation cont;
124 :
125 : struct helper
126 : {
127 : continuation * cont;
128 : using promise_type = continuation_handle_promise_type;
129 : };
130 :
131 HIT 11 : helper get_return_object()
132 : {
133 11 : return helper{&cont};
134 : }
135 : };
136 :
137 : #if defined(__GNUC__) && !defined(__clang__)
138 : #pragma GCC diagnostic push
139 : #pragma GCC diagnostic ignored "-Wmismatched-new-delete"
140 : #endif
141 :
142 : template<std::invocable<> Function, typename Allocator>
143 11 : auto make_continuation_helper(
144 : Function func,
145 : Allocator)
146 : -> continuation_handle_promise_type<Allocator>::helper
147 : {
148 : co_yield func;
149 22 : }
150 :
151 : #if defined(__GNUC__) && !defined(__clang__)
152 : #pragma GCC diagnostic pop
153 : #endif
154 :
155 : template<std::invocable<> Function, typename Allocator>
156 11 : continuation & make_continuation(
157 : Function && func,
158 : Allocator && alloc)
159 : {
160 11 : continuation * c = detail::make_continuation_helper(
161 MIS 0 : std::forward<Function>(func),
162 HIT 11 : std::forward<Allocator>(alloc)).cont;
163 11 : return *c;
164 : }
165 :
166 : }
167 :
168 :
169 : }
170 :
171 : #endif
172 :
|