Skip to content

Commit e0737ae

Browse files
authored
change __connect_awaitable to await the awaitable with no dynamic allocations (#1964)
* change `__connect_awaitable` to await the awaitable with no dynamic allocations
1 parent aa677cc commit e0737ae

12 files changed

Lines changed: 468 additions & 369 deletions

examples/hello_coro.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,25 @@
1919
#include <stdexec/execution.hpp>
2020

2121
#if !STDEXEC_NO_STDCPP_COROUTINES() && !STDEXEC_NVHPC()
22-
# include <exec/task.hpp>
2322

2423
using namespace stdexec;
2524

2625
template <sender S1, sender S2>
27-
auto async_answer(S1 s1, S2 s2) -> exec::task<int>
26+
auto async_answer(S1 s1, S2 s2) -> stdexec::task<int>
2827
{
2928
// Senders are implicitly awaitable (in this coroutine type):
3029
co_await static_cast<S2&&>(s2);
3130
co_return co_await static_cast<S1&&>(s1);
3231
}
3332

3433
template <sender S1, sender S2>
35-
auto async_answer2(S1 s1, S2 s2) -> exec::task<std::optional<int>>
34+
auto async_answer2(S1 s1, S2 s2) -> stdexec::task<std::optional<int>>
3635
{
3736
co_return co_await stopped_as_optional(async_answer(s1, s2));
3837
}
3938

4039
// tasks have an associated stop token
41-
auto async_stop_token() -> exec::task<std::optional<stdexec::inplace_stop_token>>
40+
auto async_stop_token() -> stdexec::task<std::optional<stdexec::inplace_stop_token>>
4241
{
4342
co_return co_await stopped_as_optional(get_stop_token());
4443
}

include/exec/any_sender_of.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,8 @@ namespace experimental::execution
371371

372372
void __reset() noexcept
373373
{
374-
(*__vtable_)(__any::__delete, this);
375-
__object_pointer_ = nullptr;
376-
__vtable_ = __default_storage_vtable(static_cast<__vtable_t*>(nullptr));
374+
auto* __default_vtable = __default_storage_vtable((__vtable_t*) nullptr);
375+
(*std::exchange(__vtable_, __default_vtable))(__any::__delete, this);
377376
}
378377

379378
[[nodiscard]]
@@ -561,9 +560,8 @@ namespace experimental::execution
561560

562561
void __reset() noexcept
563562
{
564-
(*__vtable_)(__any::__delete, this);
565-
__object_pointer_ = nullptr;
566-
__vtable_ = __default_storage_vtable(static_cast<__vtable_t*>(nullptr));
563+
auto* __default_vtable = __default_storage_vtable((__vtable_t*) nullptr);
564+
(*std::exchange(__vtable_, __default_vtable))(__any::__delete, this);
567565
}
568566

569567
auto __get_vtable() const noexcept -> _Vtable const *

include/exec/at_coroutine_exit.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ namespace experimental::execution
181181
{
182182
auto __cont = __h.promise().continuation();
183183
auto __coro = __h.promise().__is_stopped_ ? __cont.unhandled_stopped() : __cont.handle();
184-
return STDEXEC_DESTROY_AND_CONTINUE(__h, __coro);
184+
return STDEXEC_CORO_DESTROY_AND_CONTINUE(__h, __coro);
185185
}
186186

187187
void await_resume() const noexcept {}

include/exec/on_coro_disposition.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ namespace experimental::execution
122122
{
123123
auto __cont = __h.promise().continuation();
124124
auto __coro = __h.promise().__is_stopped_ ? __cont.unhandled_stopped() : __cont.handle();
125-
return STDEXEC_DESTROY_AND_CONTINUE(__h, __coro);
125+
return STDEXEC_CORO_DESTROY_AND_CONTINUE(__h, __coro);
126126
}
127127

128128
void await_resume() const noexcept {}

include/stdexec/__detail/__awaitable.hpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
#pragma once
1717

18+
#include "../functional.hpp"
1819
#include "__concepts.hpp"
1920
#include "__config.hpp"
2021
#include "__meta.hpp"
@@ -39,20 +40,20 @@ namespace STDEXEC
3940
__promise.await_transform(static_cast<_Awaitable &&>(__awaitable));
4041
};
4142

42-
template <class _Awaitable>
43-
constexpr auto __get_awaitable(_Awaitable &&__awaitable, __ignore = {}) -> decltype(auto)
44-
{
45-
return static_cast<_Awaitable &&>(__awaitable);
46-
}
43+
inline constexpr auto __get_awaitable = __first_callable{
44+
[]<class _Promise, __has_await_transform<_Promise> _Awaitable>(_Awaitable &&__awaitable,
45+
_Promise &__promise)
46+
-> decltype(auto)
47+
{ return __promise.await_transform(static_cast<_Awaitable &&>(__awaitable)); },
48+
[]<class _Awaitable>(_Awaitable &&__awaitable, __ignore = {}) -> decltype(auto)
49+
{ return static_cast<_Awaitable &&>(__awaitable); }};
4750

48-
template <class _Promise, __has_await_transform<_Promise> _Awaitable>
49-
constexpr auto __get_awaitable(_Awaitable &&__awaitable, _Promise &__promise) -> decltype(auto)
50-
{
51-
return __promise.await_transform(static_cast<_Awaitable &&>(__awaitable));
52-
}
51+
template <class _Awaitable, class _Promise>
52+
using __awaitable_of_t = decltype(STDEXEC::__get_awaitable(__declval<_Awaitable>(),
53+
__declval<_Promise &>()));
5354

54-
template <class _Awaitable>
55-
constexpr auto __get_awaiter(_Awaitable &&__awaitable) -> decltype(auto)
55+
inline constexpr auto __get_awaiter =
56+
[]<class _Awaitable>(_Awaitable &&__awaitable) -> decltype(auto)
5657
{
5758
if constexpr (requires { __declval<_Awaitable>().operator co_await(); })
5859
{
@@ -66,7 +67,10 @@ namespace STDEXEC
6667
{
6768
return static_cast<_Awaitable &&>(__awaitable);
6869
}
69-
}
70+
};
71+
72+
template <class _Awaitable>
73+
using __awaiter_of_t = decltype(STDEXEC::__get_awaiter(__declval<_Awaitable>()));
7074

7175
template <class _Awaitable, class... _Promise>
7276
concept __awaitable = requires(_Awaitable &&__awaitable, _Promise &...__promise) {

include/stdexec/__detail/__config.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,15 @@ namespace STDEXEC::__std
401401
# define STDEXEC_PRAGMA_IGNORE_MSVC(...)
402402
#endif
403403

404+
#if STDEXEC_MSVC()
405+
# define STDEXEC_PRAGMA_OPTIMIZE_BEGIN() STDEXEC_PRAGMA(optimize("", on))
406+
# define STDEXEC_PRAGMA_OPTIMIZE_END() STDEXEC_PRAGMA(optimize("", off))
407+
#else
408+
# define STDEXEC_PRAGMA_OPTIMIZE_BEGIN() STDEXEC_PRAGMA(GCC push_options) \
409+
STDEXEC_PRAGMA(GCC optimize("O3"))
410+
# define STDEXEC_PRAGMA_OPTIMIZE_END() STDEXEC_PRAGMA(GCC pop_options)
411+
#endif
412+
404413
#if !STDEXEC_MSVC() && defined(__has_builtin)
405414
# define STDEXEC_HAS_BUILTIN __has_builtin
406415
#else

include/stdexec/__detail/__connect.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace STDEXEC
4343
};
4444

4545
template <class _Sender, class _Receiver>
46-
concept __with_co_await = __awaitable<_Sender, __connect_await::__promise<_Receiver>>;
46+
concept __with_co_await = __awaitable<_Sender, __connect_await::__promise<_Sender, _Receiver>>;
4747

4848
template <class _Sender, class _Receiver>
4949
concept __with_legacy_tag_invoke = __tag_invocable<connect_t, _Sender, _Receiver>;

0 commit comments

Comments
 (0)