From 80adf9ab238b01ed48926dca38bf7eefd39c823d Mon Sep 17 00:00:00 2001
From: robot-piglet <robot-piglet@yandex-team.com>
Date: Mon, 29 Jul 2024 14:55:30 +0300
Subject: Intermediate changes

---
 .../cpp/threading/future/core/coroutine_traits.h   | 99 ++++++++++++++++++++++
 1 file changed, 99 insertions(+)
 create mode 100644 library/cpp/threading/future/core/coroutine_traits.h

(limited to 'library/cpp/threading/future/core')

diff --git a/library/cpp/threading/future/core/coroutine_traits.h b/library/cpp/threading/future/core/coroutine_traits.h
new file mode 100644
index 0000000000..5871e22a35
--- /dev/null
+++ b/library/cpp/threading/future/core/coroutine_traits.h
@@ -0,0 +1,99 @@
+#pragma once
+
+#include <library/cpp/threading/future/future.h>
+
+#include <coroutine>
+
+template<typename... Args>
+struct std::coroutine_traits<NThreading::TFuture<void>, Args...> {
+    struct promise_type {
+
+        NThreading::TFuture<void> get_return_object() {
+            return Promise_.GetFuture();
+        }
+
+        std::suspend_never initial_suspend() { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+
+        void unhandled_exception() {
+            Promise_.SetException(std::current_exception());
+        }
+
+        void return_void() {
+            Promise_.SetValue();
+        }
+
+    private:
+        NThreading::TPromise<void> Promise_ = NThreading::NewPromise();
+    };
+};
+
+template<typename T, typename... Args>
+struct std::coroutine_traits<NThreading::TFuture<T>, Args...> {
+    struct promise_type {
+        NThreading::TFuture<T> get_return_object() {
+            return Promise_.GetFuture();
+        }
+
+        std::suspend_never initial_suspend() { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+
+        void unhandled_exception() {
+            Promise_.SetException(std::current_exception());
+        }
+
+        void return_value(auto&& val) {
+            Promise_.SetValue(std::forward<decltype(val)>(val));
+        }
+
+    private:
+        NThreading::TPromise<T> Promise_ = NThreading::NewPromise<T>();
+    };
+};
+
+template<typename T>
+struct TFutureAwaitable {
+    NThreading::TFuture<T> Future;
+
+    TFutureAwaitable(NThreading::TFuture<T> future)
+        : Future{future}
+    {
+    }
+
+    bool await_ready() const noexcept {
+        return Future.HasValue() || Future.HasException();
+    }
+
+    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.
+         */
+        Future.NoexceptSubscribe(
+            [h](auto) mutable noexcept {
+                h();
+            }
+        );
+    }
+
+    decltype(auto) await_resume() {
+        return Future.GetValue();
+    }
+};
+
+template<typename T>
+auto operator co_await(const NThreading::TFuture<T>& future) {
+    return TFutureAwaitable{future};
+}
+
+namespace NThreading {
+
+    template<typename T>
+    auto AsAwaitable(const NThreading::TFuture<T>& fut) {
+        return operator co_await(fut);
+    }
+
+} // namespace NThreading
-- 
cgit v1.2.3