diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/threading/future/core/future.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/threading/future/core/future.h')
-rw-r--r-- | library/cpp/threading/future/core/future.h | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/library/cpp/threading/future/core/future.h b/library/cpp/threading/future/core/future.h new file mode 100644 index 0000000000..2e82bb953e --- /dev/null +++ b/library/cpp/threading/future/core/future.h @@ -0,0 +1,272 @@ +#pragma once + +#include "fwd.h" + +#include <util/datetime/base.h> +#include <util/generic/function.h> +#include <util/generic/maybe.h> +#include <util/generic/ptr.h> +#include <util/generic/vector.h> +#include <util/generic/yexception.h> +#include <util/system/event.h> +#include <util/system/spinlock.h> + +namespace NThreading { + //////////////////////////////////////////////////////////////////////////////// + + struct TFutureException: public yexception {}; + + // creates unset promise + template <typename T> + TPromise<T> NewPromise(); + TPromise<void> NewPromise(); + + // creates preset future + template <typename T> + TFuture<T> MakeFuture(const T& value); + template <typename T> + TFuture<std::remove_reference_t<T>> MakeFuture(T&& value); + template <typename T> + TFuture<T> MakeFuture(); + template <typename T> + TFuture<T> MakeErrorFuture(std::exception_ptr exception); + TFuture<void> MakeFuture(); + + //////////////////////////////////////////////////////////////////////////////// + + namespace NImpl { + template <typename T> + class TFutureState; + + template <typename T> + struct TFutureType { + using TType = T; + }; + + template <typename T> + struct TFutureType<TFuture<T>> { + using TType = typename TFutureType<T>::TType; + }; + + template <typename F, typename T> + struct TFutureCallResult { + // NOTE: separate class for msvc compatibility + using TType = decltype(std::declval<F&>()(std::declval<const TFuture<T>&>())); + }; + } + + template <typename F> + using TFutureType = typename NImpl::TFutureType<F>::TType; + + template <typename F, typename T> + using TFutureCallResult = typename NImpl::TFutureCallResult<F, T>::TType; + + //! Type of the future/promise state identifier + class TFutureStateId; + + //////////////////////////////////////////////////////////////////////////////// + + template <typename T> + class TFuture { + using TFutureState = NImpl::TFutureState<T>; + + private: + TIntrusivePtr<TFutureState> State; + + public: + using value_type = T; + + TFuture() noexcept = default; + TFuture(const TFuture<T>& other) noexcept = default; + TFuture(TFuture<T>&& other) noexcept = default; + TFuture(const TIntrusivePtr<TFutureState>& state) noexcept; + + TFuture<T>& operator=(const TFuture<T>& other) noexcept = default; + TFuture<T>& operator=(TFuture<T>&& other) noexcept = default; + void Swap(TFuture<T>& other); + + bool Initialized() const; + + bool HasValue() const; + const T& GetValue(TDuration timeout = TDuration::Zero()) const; + const T& GetValueSync() const; + T ExtractValue(TDuration timeout = TDuration::Zero()); + T ExtractValueSync(); + + void TryRethrow() const; + bool HasException() const; + + void Wait() const; + bool Wait(TDuration timeout) const; + bool Wait(TInstant deadline) const; + + template <typename F> + const TFuture<T>& Subscribe(F&& callback) const; + + // precondition: EnsureInitialized() passes + // postcondition: std::terminate is highly unlikely + template <typename F> + const TFuture<T>& NoexceptSubscribe(F&& callback) const noexcept; + + template <typename F> + TFuture<TFutureType<TFutureCallResult<F, T>>> Apply(F&& func) const; + + TFuture<void> IgnoreResult() const; + + //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional + /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death + **/ + TMaybe<TFutureStateId> StateId() const noexcept; + + void EnsureInitialized() const; + }; + + //////////////////////////////////////////////////////////////////////////////// + + template <> + class TFuture<void> { + using TFutureState = NImpl::TFutureState<void>; + + private: + TIntrusivePtr<TFutureState> State = nullptr; + + public: + using value_type = void; + + TFuture() noexcept = default; + TFuture(const TFuture<void>& other) noexcept = default; + TFuture(TFuture<void>&& other) noexcept = default; + TFuture(const TIntrusivePtr<TFutureState>& state) noexcept; + + TFuture<void>& operator=(const TFuture<void>& other) noexcept = default; + TFuture<void>& operator=(TFuture<void>&& other) noexcept = default; + void Swap(TFuture<void>& other); + + bool Initialized() const; + + bool HasValue() const; + void GetValue(TDuration timeout = TDuration::Zero()) const; + void GetValueSync() const; + + void TryRethrow() const; + bool HasException() const; + + void Wait() const; + bool Wait(TDuration timeout) const; + bool Wait(TInstant deadline) const; + + template <typename F> + const TFuture<void>& Subscribe(F&& callback) const; + + // precondition: EnsureInitialized() passes + // postcondition: std::terminate is highly unlikely + template <typename F> + const TFuture<void>& NoexceptSubscribe(F&& callback) const noexcept; + + template <typename F> + TFuture<TFutureType<TFutureCallResult<F, void>>> Apply(F&& func) const; + + template <typename R> + TFuture<R> Return(const R& value) const; + + TFuture<void> IgnoreResult() const { + return *this; + } + + //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional + /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death + **/ + TMaybe<TFutureStateId> StateId() const noexcept; + + void EnsureInitialized() const; + }; + + //////////////////////////////////////////////////////////////////////////////// + + template <typename T> + class TPromise { + using TFutureState = NImpl::TFutureState<T>; + + private: + TIntrusivePtr<TFutureState> State = nullptr; + + public: + TPromise() noexcept = default; + TPromise(const TPromise<T>& other) noexcept = default; + TPromise(TPromise<T>&& other) noexcept = default; + TPromise(const TIntrusivePtr<TFutureState>& state) noexcept; + + TPromise<T>& operator=(const TPromise<T>& other) noexcept = default; + TPromise<T>& operator=(TPromise<T>&& other) noexcept = default; + void Swap(TPromise<T>& other); + + bool Initialized() const; + + bool HasValue() const; + const T& GetValue() const; + T ExtractValue(); + + void SetValue(const T& value); + void SetValue(T&& value); + + bool TrySetValue(const T& value); + bool TrySetValue(T&& value); + + void TryRethrow() const; + bool HasException() const; + void SetException(const TString& e); + void SetException(std::exception_ptr e); + bool TrySetException(std::exception_ptr e); + + TFuture<T> GetFuture() const; + operator TFuture<T>() const; + + private: + void EnsureInitialized() const; + }; + + //////////////////////////////////////////////////////////////////////////////// + + template <> + class TPromise<void> { + using TFutureState = NImpl::TFutureState<void>; + + private: + TIntrusivePtr<TFutureState> State; + + public: + TPromise() noexcept = default; + TPromise(const TPromise<void>& other) noexcept = default; + TPromise(TPromise<void>&& other) noexcept = default; + TPromise(const TIntrusivePtr<TFutureState>& state) noexcept; + + TPromise<void>& operator=(const TPromise<void>& other) noexcept = default; + TPromise<void>& operator=(TPromise<void>&& other) noexcept = default; + void Swap(TPromise<void>& other); + + bool Initialized() const; + + bool HasValue() const; + void GetValue() const; + + void SetValue(); + bool TrySetValue(); + + void TryRethrow() const; + bool HasException() const; + void SetException(const TString& e); + void SetException(std::exception_ptr e); + bool TrySetException(std::exception_ptr e); + + TFuture<void> GetFuture() const; + operator TFuture<void>() const; + + private: + void EnsureInitialized() const; + }; + +} + +#define INCLUDE_FUTURE_INL_H +#include "future-inl.h" +#undef INCLUDE_FUTURE_INL_H |