Skip to content

Commit d85fbd8

Browse files
committed
[FOLD]
1 parent e09dca7 commit d85fbd8

1 file changed

Lines changed: 63 additions & 12 deletions

File tree

include/boost/capy/io/write_now.hpp

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,32 +114,64 @@ class write_now
114114
std::stop_token token_;
115115
bool done_ = false;
116116

117-
// GCC 14 ICEs when non-trivial types live in
118-
// coroutine frames; keep this wrapper trivial.
119-
template<class Inner>
120-
struct io_await_wrapper
117+
// GCC 14 ICEs on any template type instantiated
118+
// with an IoAwaitable in the coroutine frame, even
119+
// trivial ones. Type-erase behind function pointers
120+
// so the frame sees only a non-template struct.
121+
struct erased_io_awaiter
121122
{
122-
Inner* inner_;
123+
void* inner_;
123124
promise_type* p_;
125+
bool (*ready_)(void*);
126+
coro (*suspend_)(
127+
void*, coro,
128+
executor_ref, std::stop_token);
129+
io_result<std::size_t> (*resume_)(void*);
130+
void (*destroy_)(void*);
124131

125132
bool await_ready()
126133
{
127-
return inner_->await_ready();
134+
return ready_(inner_);
128135
}
129136

130137
coro await_suspend(coro h)
131138
{
132-
return detail::call_await_suspend(
139+
return suspend_(
133140
inner_, h,
134141
p_->ex_, p_->token_);
135142
}
136143

137-
decltype(auto) await_resume()
144+
io_result<std::size_t> await_resume()
138145
{
139-
auto r = inner_->await_resume();
140-
delete inner_;
146+
auto r = resume_(inner_);
147+
destroy_(inner_);
148+
inner_ = nullptr;
141149
return r;
142150
}
151+
152+
~erased_io_awaiter()
153+
{
154+
if(inner_)
155+
destroy_(inner_);
156+
}
157+
158+
erased_io_awaiter(
159+
erased_io_awaiter&& o) noexcept
160+
: inner_(std::exchange(o.inner_, nullptr))
161+
, p_(o.p_)
162+
, ready_(o.ready_)
163+
, suspend_(o.suspend_)
164+
, resume_(o.resume_)
165+
, destroy_(o.destroy_)
166+
{
167+
}
168+
169+
erased_io_awaiter(
170+
erased_io_awaiter const&) = delete;
171+
erased_io_awaiter& operator=(
172+
erased_io_awaiter const&) = delete;
173+
erased_io_awaiter& operator=(
174+
erased_io_awaiter&&) = delete;
143175
};
144176

145177
op_type get_return_object()
@@ -207,9 +239,28 @@ class write_now
207239
if constexpr (IoAwaitable<decayed>)
208240
{
209241
#if BOOST_CAPY_WRITE_NOW_WORKAROUND
210-
return io_await_wrapper<decayed>{
242+
return erased_io_awaiter{
211243
new decayed(std::forward<A>(a)),
212-
this};
244+
this,
245+
+[](void* v) -> bool {
246+
return static_cast<decayed*>(
247+
v)->await_ready();
248+
},
249+
+[](void* v, coro h,
250+
executor_ref ex,
251+
std::stop_token tok) -> coro {
252+
return detail::call_await_suspend(
253+
static_cast<decayed*>(v),
254+
h, ex, tok);
255+
},
256+
+[](void* v)
257+
-> io_result<std::size_t> {
258+
return static_cast<decayed*>(
259+
v)->await_resume();
260+
},
261+
+[](void* v) {
262+
delete static_cast<decayed*>(v);
263+
}};
213264
#else
214265
struct wrapper
215266
{

0 commit comments

Comments
 (0)