future.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. // returns true if exception or value was set.
  77. // allows to check readiness without locking cheker-thread
  78. // NOTE: returns true even if value was extracted from promise
  79. // good replace for HasValue() || HasException()
  80. bool IsReady() const;
  81. void Wait() const;
  82. bool Wait(TDuration timeout) const;
  83. bool Wait(TInstant deadline) const;
  84. template <typename F>
  85. const TFuture<T>& Subscribe(F&& callback) const;
  86. // precondition: EnsureInitialized() passes
  87. // postcondition: std::terminate is highly unlikely
  88. template <typename F>
  89. const TFuture<T>& NoexceptSubscribe(F&& callback) const noexcept;
  90. template <typename F>
  91. TFuture<TFutureType<TFutureCallResult<F, T>>> Apply(F&& func) const;
  92. TFuture<void> IgnoreResult() const;
  93. //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional
  94. /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death
  95. **/
  96. TMaybe<TFutureStateId> StateId() const noexcept;
  97. void EnsureInitialized() const;
  98. };
  99. ////////////////////////////////////////////////////////////////////////////////
  100. template <>
  101. class TFuture<void> {
  102. using TFutureState = NImpl::TFutureState<void>;
  103. private:
  104. TIntrusivePtr<TFutureState> State = nullptr;
  105. public:
  106. using value_type = void;
  107. TFuture() noexcept = default;
  108. TFuture(const TFuture<void>& other) noexcept = default;
  109. TFuture(TFuture<void>&& other) noexcept = default;
  110. TFuture(const TIntrusivePtr<TFutureState>& state) noexcept;
  111. TFuture<void>& operator=(const TFuture<void>& other) noexcept = default;
  112. TFuture<void>& operator=(TFuture<void>&& other) noexcept = default;
  113. void Swap(TFuture<void>& other);
  114. bool Initialized() const;
  115. bool HasValue() const;
  116. void GetValue(TDuration timeout = TDuration::Zero()) const;
  117. void GetValueSync() const;
  118. void TryRethrow() const;
  119. bool HasException() const;
  120. // returns true if exception or value was set.
  121. // allows to check readiness without locking cheker-thread
  122. // good replace for HasValue() || HasException()
  123. bool IsReady() const;
  124. void Wait() const;
  125. bool Wait(TDuration timeout) const;
  126. bool Wait(TInstant deadline) const;
  127. template <typename F>
  128. const TFuture<void>& Subscribe(F&& callback) const;
  129. // precondition: EnsureInitialized() passes
  130. // postcondition: std::terminate is highly unlikely
  131. template <typename F>
  132. const TFuture<void>& NoexceptSubscribe(F&& callback) const noexcept;
  133. template <typename F>
  134. TFuture<TFutureType<TFutureCallResult<F, void>>> Apply(F&& func) const;
  135. template <typename R>
  136. TFuture<std::remove_cvref_t<R>> Return(R&& value) const;
  137. TFuture<void> IgnoreResult() const {
  138. return *this;
  139. }
  140. //! If the future is initialized returns the future state identifier. Otherwise returns an empty optional
  141. /** The state identifier is guaranteed to be unique during the future state lifetime and could be reused after its death
  142. **/
  143. TMaybe<TFutureStateId> StateId() const noexcept;
  144. void EnsureInitialized() const;
  145. };
  146. ////////////////////////////////////////////////////////////////////////////////
  147. template <typename T>
  148. class TPromise {
  149. using TFutureState = NImpl::TFutureState<T>;
  150. private:
  151. TIntrusivePtr<TFutureState> State = nullptr;
  152. public:
  153. TPromise() noexcept = default;
  154. TPromise(const TPromise<T>& other) noexcept = default;
  155. TPromise(TPromise<T>&& other) noexcept = default;
  156. TPromise(const TIntrusivePtr<TFutureState>& state) noexcept;
  157. TPromise<T>& operator=(const TPromise<T>& other) noexcept = default;
  158. TPromise<T>& operator=(TPromise<T>&& other) noexcept = default;
  159. void Swap(TPromise<T>& other);
  160. bool Initialized() const;
  161. bool HasValue() const;
  162. const T& GetValue() const;
  163. T ExtractValue();
  164. void SetValue(const T& value);
  165. void SetValue(T&& value);
  166. bool TrySetValue(const T& value);
  167. bool TrySetValue(T&& value);
  168. void TryRethrow() const;
  169. bool HasException() const;
  170. // returns true if exception or value was set.
  171. // allows to check readiness without locking cheker-thread
  172. // NOTE: returns true even if value was extracted from promise
  173. // good replace for HasValue() || HasException()
  174. bool IsReady() const;
  175. void SetException(const TString& e);
  176. void SetException(std::exception_ptr e);
  177. bool TrySetException(std::exception_ptr e);
  178. TFuture<T> GetFuture() const;
  179. operator TFuture<T>() const;
  180. private:
  181. void EnsureInitialized() const;
  182. };
  183. ////////////////////////////////////////////////////////////////////////////////
  184. template <>
  185. class TPromise<void> {
  186. using TFutureState = NImpl::TFutureState<void>;
  187. private:
  188. TIntrusivePtr<TFutureState> State;
  189. public:
  190. TPromise() noexcept = default;
  191. TPromise(const TPromise<void>& other) noexcept = default;
  192. TPromise(TPromise<void>&& other) noexcept = default;
  193. TPromise(const TIntrusivePtr<TFutureState>& state) noexcept;
  194. TPromise<void>& operator=(const TPromise<void>& other) noexcept = default;
  195. TPromise<void>& operator=(TPromise<void>&& other) noexcept = default;
  196. void Swap(TPromise<void>& other);
  197. bool Initialized() const;
  198. bool HasValue() const;
  199. void GetValue() const;
  200. void SetValue();
  201. bool TrySetValue();
  202. void TryRethrow() const;
  203. bool HasException() const;
  204. // returns true if exception or value was set.
  205. // allows to check readiness without locking cheker-thread
  206. // good replace for HasValue() || HasException()
  207. bool IsReady() const;
  208. void SetException(const TString& e);
  209. void SetException(std::exception_ptr e);
  210. bool TrySetException(std::exception_ptr e);
  211. TFuture<void> GetFuture() const;
  212. operator TFuture<void>() const;
  213. private:
  214. void EnsureInitialized() const;
  215. };
  216. }
  217. #define INCLUDE_FUTURE_INL_H
  218. #include "future-inl.h"
  219. #undef INCLUDE_FUTURE_INL_H