diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-07-29 14:55:30 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-07-29 15:09:48 +0300 |
commit | 80adf9ab238b01ed48926dca38bf7eefd39c823d (patch) | |
tree | 0565154984fed73dc32aaf76c402f81c54ac46f6 /library/cpp/threading/future/core | |
parent | 5d639bd83a0f3642a1c2b605bcac23a25a071920 (diff) | |
download | ydb-80adf9ab238b01ed48926dca38bf7eefd39c823d.tar.gz |
Intermediate changes
Diffstat (limited to 'library/cpp/threading/future/core')
-rw-r--r-- | library/cpp/threading/future/core/coroutine_traits.h | 99 |
1 files changed, 99 insertions, 0 deletions
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 |