diff --git a/corral/detail/utility.h b/corral/detail/utility.h index 97614ba..199afc7 100644 --- a/corral/detail/utility.h +++ b/corral/detail/utility.h @@ -237,10 +237,9 @@ struct AwaitableStateChecker : ProxyFrame { break; case State::ReadyImmediately: case State::ReadyAfterCancel: - // Redundant readiness check is allowed as long as we haven't - // suspended yet (which hasExecutor is a proxy for) and - // we don't backtrack in readiness - CORRAL_ASSERT(!hasExecutor_ && val); + // Redundant readiness check is allowed as long as we don't + // backtrack in readiness + CORRAL_ASSERT(val); break; default: CORRAL_ASSERT_UNREACHABLE(); @@ -268,7 +267,8 @@ struct AwaitableStateChecker : ProxyFrame { void aboutToSetExecutor() noexcept { CORRAL_ASSERT( state_ == State::NotReady || state_ == State::CancelPending || - state_ == State::Initial || state_ == State::InitialCxlPend); + state_ == State::ReadyImmediately || state_ == State::Initial || + state_ == State::InitialCxlPend); hasExecutor_ = true; } Handle aboutToSuspend(Handle h) noexcept { @@ -404,11 +404,7 @@ template class AwaitableLambda { bool await_ready() const noexcept { return false; } void await_set_executor(Executor* ex) noexcept { - if (!task_) { - task_ = callable_(); - awaitable_ = task_.operator co_await(); - } - awaitable_.await_set_executor(ex); + awaitable().await_set_executor(ex); } auto await_suspend(Handle h) { return awaitable_.await_suspend(h); } decltype(auto) await_resume() { @@ -416,10 +412,7 @@ template class AwaitableLambda { } auto await_early_cancel() noexcept { - CORRAL_ASSERT(!task_); - task_ = callable_(); - awaitable_ = task_.operator co_await(); - return awaitable_.await_early_cancel(); + return awaitable().await_early_cancel(); } auto await_cancel(Handle h) noexcept { return awaitable_.await_cancel(h); } auto await_must_resume() const noexcept { @@ -431,6 +424,15 @@ template class AwaitableLambda { } private: + AwaitableT& awaitable() { + if (!task_) { + task_ = callable_(); + awaitable_ = task_.operator co_await(); + } + + return awaitable_; + } + Callable callable_; TaskT task_; AwaitableT awaitable_; diff --git a/test/basic_test.cc b/test/basic_test.cc index 27d5e09..515e7f1 100644 --- a/test/basic_test.cc +++ b/test/basic_test.cc @@ -334,6 +334,11 @@ CORRAL_TEST_CASE("anyof") { CATCH_CHECK(&*rx == &x); CATCH_CHECK(!s2); } + + CATCH_SECTION("immediate-lambda") { + co_await anyOf(Ready{}, [&]() -> Task<> { co_await t.sleep(1ms); }); + CATCH_CHECK(t.now() == 0ms); + } } CORRAL_TEST_CASE("mostof") { @@ -394,6 +399,16 @@ CORRAL_TEST_CASE("allof") { CATCH_CHECK(t.now() == 5ms); } + CATCH_SECTION("immediate-front") { + co_await allOf(Ready{}, [&t]() -> Task<> { co_await t.sleep(1ms); }); + CATCH_CHECK(t.now() == 1ms); + } + + CATCH_SECTION("immediate-back") { + co_await allOf([&t]() -> Task<> { co_await t.sleep(1ms); }, Ready{}); + CATCH_CHECK(t.now() == 1ms); + } + CATCH_SECTION("empty") { auto r = co_await allOf(); static_assert(std::tuple_size_v == 0); diff --git a/test/config.h b/test/config.h index b52c941..fac1e2a 100644 --- a/test/config.h +++ b/test/config.h @@ -9,8 +9,8 @@ // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,