aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/threading
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-08-06 05:41:38 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-08-06 05:50:00 +0300
commitfd63b546ecde6050e2aa37e80163612446d56ff4 (patch)
treee21aebf6ea4ae187de641efaaf93faadec814e7e /library/cpp/threading
parent7e4871a90ed022841bf02fc2908d005f51c6b53b (diff)
downloadydb-fd63b546ecde6050e2aa37e80163612446d56ff4.tar.gz
Intermediate changes
Diffstat (limited to 'library/cpp/threading')
-rw-r--r--library/cpp/threading/future/core/coroutine_traits.h58
-rw-r--r--library/cpp/threading/future/ut_gtest/coroutine_traits_ut.cpp18
2 files changed, 60 insertions, 16 deletions
diff --git a/library/cpp/threading/future/core/coroutine_traits.h b/library/cpp/threading/future/core/coroutine_traits.h
index f032190fb1..cdd3eeeff3 100644
--- a/library/cpp/threading/future/core/coroutine_traits.h
+++ b/library/cpp/threading/future/core/coroutine_traits.h
@@ -4,7 +4,7 @@
#include <coroutine>
-template<typename... Args>
+template <typename... Args>
struct std::coroutine_traits<NThreading::TFuture<void>, Args...> {
struct promise_type {
@@ -28,7 +28,7 @@ struct std::coroutine_traits<NThreading::TFuture<void>, Args...> {
};
};
-template<typename T, typename... Args>
+template <typename T, typename... Args>
struct std::coroutine_traits<NThreading::TFuture<T>, Args...> {
struct promise_type {
NThreading::TFuture<T> get_return_object() {
@@ -53,11 +53,16 @@ struct std::coroutine_traits<NThreading::TFuture<T>, Args...> {
namespace NThreading {
- template<typename T>
+ template <typename T, bool Extracting = false>
struct TFutureAwaitable {
NThreading::TFuture<T> Future;
- TFutureAwaitable(NThreading::TFuture<T> future) noexcept
+ TFutureAwaitable(const NThreading::TFuture<T>& future) noexcept requires (!Extracting)
+ : Future{future}
+ {
+ }
+
+ TFutureAwaitable(NThreading::TFuture<T>&& future) noexcept
: Future{std::move(future)}
{
}
@@ -68,12 +73,12 @@ namespace NThreading {
void await_suspend(auto h) noexcept {
/*
- * This library assumes that resume never throws an exception.
- * This assumption is made due to the fact that the users of these library in most cases do not need to write their own coroutine handlers,
- * and all coroutine handlers provided by the library do not throw exception from resume.
- *
- * WARNING: do not change subscribe to apply or something other here, creating an extra future state degrades performance.
- */
+ * This library assumes that resume never throws an exception.
+ * This assumption is made due to the fact that the users of these library in most cases do not need to write their own coroutine handlers,
+ * and all coroutine handlers provided by the library do not throw exception from resume.
+ *
+ * WARNING: do not change subscribe to apply or something other here, creating an extra future state degrades performance.
+ */
Future.NoexceptSubscribe(
[h](auto) mutable noexcept {
h();
@@ -82,22 +87,43 @@ namespace NThreading {
}
decltype(auto) await_resume() {
- return Future.GetValue();
+ if constexpr (Extracting && !std::is_same_v<T, void>) { // Future<void> has only GetValue()
+ return Future.ExtractValue();
+ } else {
+ return Future.GetValue();
+ }
}
};
+ template <typename T>
+ using TExtractingFutureAwaitable = TFutureAwaitable<T, true>;
+
} // namespace NThreading
-template<typename T>
-auto operator co_await(const NThreading::TFuture<T>& future) {
+template <typename T>
+auto operator co_await(const NThreading::TFuture<T>& future) noexcept {
return NThreading::TFutureAwaitable{future};
}
+template <typename T>
+auto operator co_await(NThreading::TFuture<T>&& 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)};
+}
+
namespace NThreading {
- template<typename T>
- auto AsAwaitable(const NThreading::TFuture<T>& fut) {
- return operator co_await(fut);
+ template <typename T>
+ auto AsAwaitable(const NThreading::TFuture<T>& fut) noexcept {
+ return TFutureAwaitable(fut);
+ }
+
+ template <typename T>
+ auto AsExtractingAwaitable(NThreading::TFuture<T>&& fut) noexcept {
+ return TExtractingFutureAwaitable<T>(std::move(fut));
}
} // namespace NThreading
diff --git a/library/cpp/threading/future/ut_gtest/coroutine_traits_ut.cpp b/library/cpp/threading/future/ut_gtest/coroutine_traits_ut.cpp
index a98e455c58..2daa1f5e47 100644
--- a/library/cpp/threading/future/ut_gtest/coroutine_traits_ut.cpp
+++ b/library/cpp/threading/future/ut_gtest/coroutine_traits_ut.cpp
@@ -187,3 +187,21 @@ TEST(TestFutureTraits, CrashOnExceptionInCoroutineHandlerResume) {
#endif
);
}
+
+TEST(ExtractingFutureAwaitable, Simple) {
+ NThreading::TPromise<THolder<size_t>> suspendPromise = NThreading::NewPromise<THolder<size_t>>();
+ auto coro = [](NThreading::TFuture<THolder<size_t>> future) -> NThreading::TFuture<THolder<size_t>> {
+ auto value = co_await NThreading::AsExtractingAwaitable(std::move(future));
+ co_return value;
+ };
+
+ NThreading::TFuture<THolder<size_t>> getHolder = coro(suspendPromise.GetFuture());
+ EXPECT_FALSE(getHolder.HasValue());
+ EXPECT_FALSE(getHolder.HasException());
+ suspendPromise.SetValue(MakeHolder<size_t>(42));
+
+ EXPECT_TRUE(getHolder.HasValue());
+ auto holder = getHolder.ExtractValue();
+ ASSERT_NE(holder, nullptr);
+ EXPECT_EQ(*holder, 42u);
+}