123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #pragma once
- #include "fwd.h"
- #include <library/cpp/deprecated/atomic/atomic.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
|