aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/threading/future/core/future.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/threading/future/core/future.h
downloadydb-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.h272
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