From b9e5d6b2d3ad4bbc52ffa3291decb2d2d95d04c0 Mon Sep 17 00:00:00 2001 From: snaury Date: Tue, 1 Jul 2025 10:25:33 +0300 Subject: Fix co_await argument dependent lookup for TFuture commit_hash:d3da906e0b3f303ead8bf1257a3cdceed2778d90 --- .../cpp/threading/future/core/coroutine_traits.h | 28 ++++++------- .../future/ut_gtest/coroutine_traits_adl_ut.cpp | 24 +++++++++++ .../cpp/threading/future/ut_gtest/simple_task.h | 47 ++++++++++++++++++++++ library/cpp/threading/future/ut_gtest/ya.make | 1 + 4 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 library/cpp/threading/future/ut_gtest/coroutine_traits_adl_ut.cpp create mode 100644 library/cpp/threading/future/ut_gtest/simple_task.h (limited to 'library/cpp/threading/future') diff --git a/library/cpp/threading/future/core/coroutine_traits.h b/library/cpp/threading/future/core/coroutine_traits.h index de08c377b16..14c5539eae0 100644 --- a/library/cpp/threading/future/core/coroutine_traits.h +++ b/library/cpp/threading/future/core/coroutine_traits.h @@ -126,23 +126,19 @@ namespace NThreading { template using TExtractingFutureAwaitable = TFutureAwaitable; -} // namespace NThreading - -template -auto operator co_await(const NThreading::TFuture& future) noexcept { - return NThreading::TFutureAwaitable{future}; -} - -template -auto operator co_await(NThreading::TFuture&& future) noexcept { - // Not TExtractongFutureAwaitable, because TFuture works like std::shared_future. - // auto value = co_await GetCachedFuture(); - // If GetCachedFuture stores a future in some cache and returns its copies, - // then subsequent uses of co_await will return a moved-from value. - return NThreading::TFutureAwaitable{std::move(future)}; -} + template + auto operator co_await(const NThreading::TFuture& future) noexcept { + return NThreading::TFutureAwaitable{future}; + } -namespace NThreading { + template + auto operator co_await(NThreading::TFuture&& future) noexcept { + // Not TExtractongFutureAwaitable, because TFuture works like std::shared_future. + // auto value = co_await GetCachedFuture(); + // If GetCachedFuture stores a future in some cache and returns its copies, + // then subsequent uses of co_await will return a moved-from value. + return NThreading::TFutureAwaitable{std::move(future)}; + } template auto AsAwaitable(const NThreading::TFuture& fut) noexcept { diff --git a/library/cpp/threading/future/ut_gtest/coroutine_traits_adl_ut.cpp b/library/cpp/threading/future/ut_gtest/coroutine_traits_adl_ut.cpp new file mode 100644 index 00000000000..317dcb73c03 --- /dev/null +++ b/library/cpp/threading/future/ut_gtest/coroutine_traits_adl_ut.cpp @@ -0,0 +1,24 @@ +#include "simple_task.h" + +#include +#include +#include +#include + +TEST(TestFutureTraits, ArgumentDependentLookup) { + TVector result; + NThreading::TPromise promise = NThreading::NewPromise(); + NThreading::TFuture future = promise.GetFuture(); + + NSimpleTestTask::RunAwaitable(result, std::move(future)); + + promise.SetValue(); + + EXPECT_THAT( + result, + ::testing::ContainerEq( + TVector({ + "before co_await", + "after co_await", + }))); +} diff --git a/library/cpp/threading/future/ut_gtest/simple_task.h b/library/cpp/threading/future/ut_gtest/simple_task.h new file mode 100644 index 00000000000..8291de2dba0 --- /dev/null +++ b/library/cpp/threading/future/ut_gtest/simple_task.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#include +#include + +// Note: this namespace must be separate from NThreading and global namespace +namespace NSimpleTestTask { + + /** + * The simplest possible coroutine type for testing + */ + struct TSimpleTask { + struct promise_type { + TSimpleTask get_return_object() noexcept { + return {}; + } + std::suspend_never initial_suspend() noexcept { + return {}; + } + std::suspend_never final_suspend() noexcept { + return {}; + } + void unhandled_exception() { + throw; + } + void return_void() noexcept { + } + }; + }; + + /** + * This coroutine awaits a generic awaitable + * + * When operator co_await for awaitables is not defined before this header + * is included it will be searched using argument dependent lookup. + */ + template + TSimpleTask RunAwaitable(TVector& result, TAwaitable&& awaitable) { + result.push_back("before co_await"); + co_await std::forward(awaitable); + result.push_back("after co_await"); + } + +} // namespace NSimpleTestTask diff --git a/library/cpp/threading/future/ut_gtest/ya.make b/library/cpp/threading/future/ut_gtest/ya.make index 84f7ebe2e0e..509180f9918 100644 --- a/library/cpp/threading/future/ut_gtest/ya.make +++ b/library/cpp/threading/future/ut_gtest/ya.make @@ -5,6 +5,7 @@ PEERDIR( ) SRCS( + coroutine_traits_adl_ut.cpp coroutine_traits_ut.cpp ) -- cgit v1.3