Skip to content

Commit 04ef142

Browse files
committed
no_copy_awaitable
1 parent 276ebc1 commit 04ef142

File tree

2 files changed

+65
-20
lines changed

2 files changed

+65
-20
lines changed

strings/base_coroutine_foundation.h

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -283,46 +283,68 @@ namespace winrt::impl
283283
};
284284

285285
template <typename T>
286-
struct member_await_adapter_impl
286+
struct free_await_adapter_impl
287287
{
288288
T&& awaitable;
289289

290-
bool ready() noexcept
290+
bool ready()
291291
{
292292
return await_ready(awaitable);
293293
}
294294

295295
template <typename U>
296-
auto suspend(std::experimental::coroutine_handle<U> handle) noexcept
296+
auto suspend(std::experimental::coroutine_handle<U> handle)
297297
{
298298
return await_suspend(awaitable, handle);
299299
}
300300

301-
auto resume() noexcept
301+
auto resume()
302302
{
303303
return await_resume(awaitable);
304304
}
305305
};
306306

307+
template <typename T>
308+
struct free_await_adapter
309+
{
310+
T&& awaitable;
311+
312+
bool await_ready()
313+
{
314+
return free_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.ready();
315+
}
316+
317+
template <typename U>
318+
auto await_suspend(std::experimental::coroutine_handle<U> handle)
319+
{
320+
return free_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.suspend(handle);
321+
}
322+
323+
auto await_resume()
324+
{
325+
return free_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.resume();
326+
}
327+
};
328+
307329
template <typename T>
308330
struct member_await_adapter
309331
{
310332
T&& awaitable;
311333

312-
bool await_ready() noexcept
334+
bool await_ready()
313335
{
314-
return member_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.ready();
336+
return awaitable.await_ready();
315337
}
316338

317339
template <typename U>
318-
auto await_suspend(std::experimental::coroutine_handle<U> handle) noexcept
340+
auto await_suspend(std::experimental::coroutine_handle<U> handle)
319341
{
320-
return member_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.suspend(handle);
342+
return awaitable.await_suspend(handle);
321343
}
322344

323-
auto await_resume() noexcept
345+
auto await_resume()
324346
{
325-
return member_await_adapter_impl<T>{ static_cast<T&&>(awaitable) }.resume();
347+
return awaitable.await_resume();
326348
}
327349
};
328350

@@ -341,44 +363,48 @@ namespace winrt::impl
341363
template <typename T, std::enable_if_t<has_awaitable_member<T>::value, int> = 0>
342364
auto get_awaiter(T&& value) noexcept
343365
{
344-
return static_cast<T&&>(value);
366+
return member_await_adapter<T>{ static_cast<T&&>(value) };
345367
}
346368

347369
template <typename T, std::enable_if_t<has_awaitable_free<T>::value, int> = 0>
348370
auto get_awaiter(T&& value) noexcept
349371
{
350-
return member_await_adapter<T>{ static_cast<T&&>(value) };
372+
return free_await_adapter<T>{ static_cast<T&&>(value) };
351373
}
352374

353375
template <typename T>
354376
struct notify_awaiter
355377
{
356-
T&& awaitable;
378+
decltype(get_awaiter(std::declval<T&&>())) awaitable;
379+
380+
notify_awaiter(T&& awaitable) : awaitable(get_awaiter(static_cast<T&&>(awaitable)))
381+
{
382+
}
357383

358-
bool await_ready() noexcept
384+
bool await_ready()
359385
{
360386
if (winrt_suspend_handler)
361387
{
362388
winrt_suspend_handler(this);
363389
}
364390

365-
return get_awaiter(static_cast<T&&>(awaitable)).await_ready();
391+
return awaitable.await_ready();
366392
}
367393

368394
template <typename U>
369-
auto await_suspend(std::experimental::coroutine_handle<U> handle) noexcept
395+
auto await_suspend(std::experimental::coroutine_handle<U> handle)
370396
{
371-
return get_awaiter(static_cast<T&&>(awaitable)).await_suspend(handle);
397+
return awaitable.await_suspend(handle);
372398
}
373399

374-
auto await_resume() noexcept
400+
auto await_resume()
375401
{
376402
if (winrt_resume_handler)
377403
{
378404
winrt_resume_handler(this);
379405
}
380406

381-
return get_awaiter(static_cast<T&&>(awaitable)).await_resume();
407+
return awaitable.await_resume();
382408
}
383409
};
384410

test/test/notify_awaiter.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@ namespace
8787
}
8888
};
8989

90+
struct no_copy_awaitable
91+
{
92+
no_copy_awaitable() = default;
93+
no_copy_awaitable(no_copy_awaitable const&) = delete;
94+
95+
bool await_ready()
96+
{
97+
return true;
98+
}
99+
void await_suspend(std::experimental::coroutine_handle<>)
100+
{
101+
}
102+
void await_resume()
103+
{
104+
105+
}
106+
};
107+
90108
IAsyncAction AsyncAction()
91109
{
92110
co_return;
@@ -113,14 +131,15 @@ namespace
113131
co_await member_awaitable{};
114132
co_await free_operator_awaitable{};
115133
co_await member_operator_awaitable{};
134+
co_await no_copy_awaitable{};
116135
co_await AsyncAction();
117136
co_await AsyncActionWithProgress();
118137
co_await AsyncOperation();
119138
co_await AsyncOperationWithProgress();
120139
}
121140

122141
constexpr size_t test_coroutines = 10;
123-
constexpr size_t test_suspension_points = 11;
142+
constexpr size_t test_suspension_points = 12;
124143
}
125144

126145
TEST_CASE("notify_awaiter")

0 commit comments

Comments
 (0)