future.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #pragma once
  2. #include "fwd.h"
  3. #include <library/cpp/deprecated/atomic/atomic.h>
  4. #include <util/datetime/base.h>
  5. #include <util/generic/function.h>
  6. #include <util/generic/maybe.h>
  7. #include <util/generic/ptr.h>
  8. #include <util/generic/vector.h>
  9. #include <util/generic/yexception.h>
  10. #include <util/system/event.h>
  11. #include <util/system/spinlock.h>
  12. namespace NThreading {
  13. ////////////////////////////////////////////////////////////////////////////////
  14. struct TFutureException: public yexception {};
  15. // creates unset promise
  16. template <typename T>
  17. TPromise<T> NewPromise();
  18. TPromise<void> NewPromise();
  19. // creates preset future
  20. template <typename T>
  21. TFuture<T> MakeFuture(const T& value);
  22. template <typename T>
  23. TFuture<std::remove_reference_t<T>> MakeFuture(T&& value);
  24. template <typename T>
  25. TFuture<T> MakeFuture();
  26. template <typename T>
  27. TFuture<T> MakeErrorFuture(std::exception_ptr exception);
  28. TFuture<void> MakeFuture();
  29. ////////////////////////////////////////////////////////////////////////////////
  30. namespace NImpl {
  31. template <typename T>
  32. class TFutureState;
  33. template <typename T>
  34. struct TFutureType {
  35. using TType = T;
  36. };
  37. template <typename T>
  38. struct TFutureType<TFuture<T>> {
  39. using TType = typename TFutureType<T>::TType;
  40. };
  41. template <typename F, typename T>
  42. struct TFutureCallResult {
  43. // NOTE: separate class for msvc compatibility
  44. using TType = decltype(std::declval<F&>()(std::declval<const TFuture<T>&>()));
  45. };
  46. }
  47. template <typename F>
  48. using TFutureType = typename NImpl::TFutureType<F>::TType;
  49. template <typename F, typename T>
  50. using TFutureCallResult = typename NImpl::TFutureCallResult<F, T>::TType;
  51. //! Type of the future/promise state identifier
  52. class TFutureStateId;
  53. ////////////////////////////////////////////////////////////////////////////////
  54. template <typename T>
  55. class TFuture {
  56. using TFutureState = NImpl::TFutureState<T>;
  57. private:
  58. TIntrusivePtr<TFutureState> State;
  59. public:
  60. using value_type = T;
  61. TFuture() noexcept = default;
  62. TFuture(const TFuture<T>& other) noexcept = default;
  63. TFuture(TFuture<T>&& other) noexcept = default;
  64. TFuture(const TIntrusivePtr<TFutureState>& state) noexcept;
  65. TFuture<T>& operator=(const TFuture<T>& other) noexcept = default;
  66. TFuture<T>& operator=(TFuture<T>&& other) noexcept = default;
  67. void Swap(TFuture<T>& other);
  68. bool Initialized() const;
  69. bool HasValue() const;
  70. const T& GetValue(TDuration timeout = TDuration::Zero()) const;
  71. const T& GetValueSync() const;
  72. T ExtractValue(TDuration timeout = TDuration::Zero());
  73. T ExtractValueSync();
  74. void TryRethrow() const;
  75. bool HasException() const;
  76. void Wait() const;
  77. bool Wait(TDuration timeout) const;
  78. bool Wait(TInstant deadline) const;
  79. template <typename F>
  80. const TFuture<T>& Subscribe(F&& callback) const;
  81. // precondition: EnsureInitialized() passes
  82. // postcondition: std::terminate is highly unlikely
  83. template <typename F>
  84. const TFuture<T>& NoexceptSubscribe(F&& callback) const noexcept;
  85. template <typename F>
  86. TFuture<TFutureType<TFutureCallResult<F, T>>> Apply(F&& func) const;
  87. TFuture<void> IgnoreResult() const;
  88. //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional
  89. /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death
  90. **/
  91. TMaybe<TFutureStateId> StateId() const noexcept;
  92. void EnsureInitialized() const;
  93. };
  94. ////////////////////////////////////////////////////////////////////////////////
  95. template <>
  96. class TFuture<void> {
  97. using TFutureState = NImpl::TFutureState<void>;
  98. private:
  99. TIntrusivePtr<TFutureState> State = nullptr;
  100. public:
  101. using value_type = void;
  102. TFuture() noexcept = default;
  103. TFuture(const TFuture<void>& other) noexcept = default;
  104. TFuture(TFuture<void>&& other) noexcept = default;
  105. TFuture(const TIntrusivePtr<TFutureState>& state) noexcept;
  106. TFuture<void>& operator=(const TFuture<void>& other) noexcept = default;
  107. TFuture<void>& operator=(TFuture<void>&& other) noexcept = default;
  108. void Swap(TFuture<void>& other);
  109. bool Initialized() const;
  110. bool HasValue() const;
  111. void GetValue(TDuration timeout = TDuration::Zero()) const;
  112. void GetValueSync() const;
  113. void TryRethrow() const;
  114. bool HasException() const;
  115. void Wait() const;
  116. bool Wait(TDuration timeout) const;
  117. bool Wait(TInstant deadline) const;
  118. template <typename F>
  119. const TFuture<void>& Subscribe(F&& callback) const;
  120. // precondition: EnsureInitialized() passes
  121. // postcondition: std::terminate is highly unlikely
  122. template <typename F>
  123. const TFuture<void>& NoexceptSubscribe(F&& callback) const noexcept;
  124. template <typename F>
  125. TFuture<TFutureType<TFutureCallResult<F, void>>> Apply(F&& func) const;
  126. template <typename R>
  127. TFuture<std::remove_cvref_t<R>> Return(R&& value) const;
  128. TFuture<void> IgnoreResult() const {
  129. return *this;
  130. }
  131. //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional
  132. /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death
  133. **/
  134. TMaybe<TFutureStateId> StateId() const noexcept;
  135. void EnsureInitialized() const;
  136. };
  137. ////////////////////////////////////////////////////////////////////////////////
  138. template <typename T>
  139. class TPromise {
  140. using TFutureState = NImpl::TFutureState<T>;
  141. private:
  142. TIntrusivePtr<TFutureState> State = nullptr;
  143. public:
  144. TPromise() noexcept = default;
  145. TPromise(const TPromise<T>& other) noexcept = default;
  146. TPromise(TPromise<T>&& other) noexcept = default;
  147. TPromise(const TIntrusivePtr<TFutureState>& state) noexcept;
  148. TPromise<T>& operator=(const TPromise<T>& other) noexcept = default;
  149. TPromise<T>& operator=(TPromise<T>&& other) noexcept = default;
  150. void Swap(TPromise<T>& other);
  151. bool Initialized() const;
  152. bool HasValue() const;
  153. const T& GetValue() const;
  154. T ExtractValue();
  155. void SetValue(const T& value);
  156. void SetValue(T&& value);
  157. bool TrySetValue(const T& value);
  158. bool TrySetValue(T&& value);
  159. void TryRethrow() const;
  160. bool HasException() const;
  161. void SetException(const TString& e);
  162. void SetException(std::exception_ptr e);
  163. bool TrySetException(std::exception_ptr e);
  164. TFuture<T> GetFuture() const;
  165. operator TFuture<T>() const;
  166. private:
  167. void EnsureInitialized() const;
  168. };
  169. ////////////////////////////////////////////////////////////////////////////////
  170. template <>
  171. class TPromise<void> {
  172. using TFutureState = NImpl::TFutureState<void>;
  173. private:
  174. TIntrusivePtr<TFutureState> State;
  175. public:
  176. TPromise() noexcept = default;
  177. TPromise(const TPromise<void>& other) noexcept = default;
  178. TPromise(TPromise<void>&& other) noexcept = default;
  179. TPromise(const TIntrusivePtr<TFutureState>& state) noexcept;
  180. TPromise<void>& operator=(const TPromise<void>& other) noexcept = default;
  181. TPromise<void>& operator=(TPromise<void>&& other) noexcept = default;
  182. void Swap(TPromise<void>& other);
  183. bool Initialized() const;
  184. bool HasValue() const;
  185. void GetValue() const;
  186. void SetValue();
  187. bool TrySetValue();
  188. void TryRethrow() const;
  189. bool HasException() const;
  190. void SetException(const TString& e);
  191. void SetException(std::exception_ptr e);
  192. bool TrySetException(std::exception_ptr e);
  193. TFuture<void> GetFuture() const;
  194. operator TFuture<void>() const;
  195. private:
  196. void EnsureInitialized() const;
  197. };
  198. }
  199. #define INCLUDE_FUTURE_INL_H
  200. #include "future-inl.h"
  201. #undef INCLUDE_FUTURE_INL_H