future.h 8.3 KB

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