future-inl.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. #pragma once
  2. #if !defined(INCLUDE_FUTURE_INL_H)
  3. #error "you should never include future-inl.h directly"
  4. #include "future.h" // Fix LSP
  5. #endif // INCLUDE_FUTURE_INL_H
  6. namespace NThreading {
  7. namespace NImpl {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. template <typename T>
  10. using TCallback = std::function<void(const TFuture<T>&)>;
  11. template <typename T>
  12. using TCallbackList = TVector<TCallback<T>>; // TODO: small vector
  13. ////////////////////////////////////////////////////////////////////////////////
  14. [[noreturn]] void ThrowFutureException(TStringBuf message, const TSourceLocation& source);
  15. enum class TError {
  16. Error
  17. };
  18. template <typename T>
  19. class TFutureState: public TAtomicRefCount<TFutureState<T>> {
  20. enum {
  21. NotReady,
  22. ExceptionSet,
  23. ValueMoved, // keep the ordering of this and following values
  24. ValueSet,
  25. ValueRead,
  26. };
  27. private:
  28. mutable TAtomic State;
  29. TAdaptiveLock StateLock;
  30. TCallbackList<T> Callbacks;
  31. mutable THolder<TSystemEvent> ReadyEvent;
  32. std::exception_ptr Exception;
  33. union {
  34. char NullValue;
  35. T Value;
  36. };
  37. void AccessValue(TDuration timeout, int acquireState) const {
  38. TAtomicBase state = AtomicGet(State);
  39. if (Y_UNLIKELY(state == NotReady)) {
  40. if (timeout == TDuration::Zero()) {
  41. ::NThreading::NImpl::ThrowFutureException("value not set"sv, __LOCATION__);
  42. }
  43. if (!Wait(timeout)) {
  44. ::NThreading::NImpl::ThrowFutureException("wait timeout"sv, __LOCATION__);
  45. }
  46. state = AtomicGet(State);
  47. }
  48. TryRethrowWithState(state);
  49. switch (AtomicGetAndCas(&State, acquireState, ValueSet)) {
  50. case ValueSet:
  51. break;
  52. case ValueRead:
  53. if (acquireState != ValueRead) {
  54. ::NThreading::NImpl::ThrowFutureException("value being read"sv, __LOCATION__);
  55. }
  56. break;
  57. case ValueMoved:
  58. ::NThreading::NImpl::ThrowFutureException("value was moved"sv, __LOCATION__);
  59. default:
  60. Y_ASSERT(state == ValueSet);
  61. }
  62. }
  63. public:
  64. TFutureState()
  65. : State(NotReady)
  66. , NullValue(0)
  67. {
  68. }
  69. template <typename TT>
  70. TFutureState(TT&& value)
  71. : State(ValueSet)
  72. , Value(std::forward<TT>(value))
  73. {
  74. }
  75. TFutureState(std::exception_ptr exception, TError)
  76. : State(ExceptionSet)
  77. , Exception(std::move(exception))
  78. , NullValue(0)
  79. {
  80. }
  81. ~TFutureState() {
  82. if (State >= ValueMoved) { // ValueMoved, ValueSet, ValueRead
  83. Value.~T();
  84. }
  85. }
  86. bool HasValue() const {
  87. return AtomicGet(State) >= ValueMoved; // ValueMoved, ValueSet, ValueRead
  88. }
  89. void TryRethrow() const {
  90. TAtomicBase state = AtomicGet(State);
  91. TryRethrowWithState(state);
  92. }
  93. bool HasException() const {
  94. return AtomicGet(State) == ExceptionSet;
  95. }
  96. bool IsReady() const {
  97. return AtomicGet(State) != NotReady;
  98. }
  99. const T& GetValue(TDuration timeout = TDuration::Zero()) const {
  100. AccessValue(timeout, ValueRead);
  101. return Value;
  102. }
  103. T ExtractValue(TDuration timeout = TDuration::Zero()) {
  104. AccessValue(timeout, ValueMoved);
  105. return std::move(Value);
  106. }
  107. template <typename TT>
  108. void SetValue(TT&& value) {
  109. bool success = TrySetValue(std::forward<TT>(value));
  110. if (Y_UNLIKELY(!success)) {
  111. ::NThreading::NImpl::ThrowFutureException("value already set"sv, __LOCATION__);
  112. }
  113. }
  114. template <typename TT>
  115. bool TrySetValue(TT&& value) {
  116. TSystemEvent* readyEvent = nullptr;
  117. TCallbackList<T> callbacks;
  118. with_lock (StateLock) {
  119. TAtomicBase state = AtomicGet(State);
  120. if (Y_UNLIKELY(state != NotReady)) {
  121. return false;
  122. }
  123. new (&Value) T(std::forward<TT>(value));
  124. readyEvent = ReadyEvent.Get();
  125. callbacks = std::move(Callbacks);
  126. AtomicSet(State, ValueSet);
  127. }
  128. if (readyEvent) {
  129. readyEvent->Signal();
  130. }
  131. if (callbacks) {
  132. TFuture<T> temp(this);
  133. for (auto& callback : callbacks) {
  134. callback(temp);
  135. }
  136. }
  137. return true;
  138. }
  139. void SetException(std::exception_ptr e) {
  140. bool success = TrySetException(std::move(e));
  141. if (Y_UNLIKELY(!success)) {
  142. ::NThreading::NImpl::ThrowFutureException("value already set"sv, __LOCATION__);
  143. }
  144. }
  145. bool TrySetException(std::exception_ptr e) {
  146. TSystemEvent* readyEvent;
  147. TCallbackList<T> callbacks;
  148. with_lock (StateLock) {
  149. TAtomicBase state = AtomicGet(State);
  150. if (Y_UNLIKELY(state != NotReady)) {
  151. return false;
  152. }
  153. Exception = std::move(e);
  154. readyEvent = ReadyEvent.Get();
  155. callbacks = std::move(Callbacks);
  156. AtomicSet(State, ExceptionSet);
  157. }
  158. if (readyEvent) {
  159. readyEvent->Signal();
  160. }
  161. if (callbacks) {
  162. TFuture<T> temp(this);
  163. for (auto& callback : callbacks) {
  164. callback(temp);
  165. }
  166. }
  167. return true;
  168. }
  169. template <typename F>
  170. bool Subscribe(F&& func) {
  171. with_lock (StateLock) {
  172. TAtomicBase state = AtomicGet(State);
  173. if (state == NotReady) {
  174. Callbacks.emplace_back(std::forward<F>(func));
  175. return true;
  176. }
  177. }
  178. return false;
  179. }
  180. void Wait() const {
  181. Wait(TInstant::Max());
  182. }
  183. bool Wait(TDuration timeout) const {
  184. return Wait(timeout.ToDeadLine());
  185. }
  186. bool Wait(TInstant deadline) const {
  187. TSystemEvent* readyEvent = nullptr;
  188. with_lock (StateLock) {
  189. TAtomicBase state = AtomicGet(State);
  190. if (state != NotReady) {
  191. return true;
  192. }
  193. if (!ReadyEvent) {
  194. ReadyEvent.Reset(new TSystemEvent());
  195. }
  196. readyEvent = ReadyEvent.Get();
  197. }
  198. Y_ASSERT(readyEvent);
  199. return readyEvent->WaitD(deadline);
  200. }
  201. void TryRethrowWithState(TAtomicBase state) const {
  202. if (Y_UNLIKELY(state == ExceptionSet)) {
  203. Y_ASSERT(Exception);
  204. std::rethrow_exception(Exception);
  205. }
  206. }
  207. };
  208. ////////////////////////////////////////////////////////////////////////////////
  209. template <>
  210. class TFutureState<void>: public TAtomicRefCount<TFutureState<void>> {
  211. enum {
  212. NotReady,
  213. ValueSet,
  214. ExceptionSet,
  215. };
  216. private:
  217. TAtomic State;
  218. TAdaptiveLock StateLock;
  219. TCallbackList<void> Callbacks;
  220. mutable THolder<TSystemEvent> ReadyEvent;
  221. std::exception_ptr Exception;
  222. public:
  223. TFutureState(bool valueSet = false)
  224. : State(valueSet ? ValueSet : NotReady)
  225. {
  226. }
  227. TFutureState(std::exception_ptr exception, TError)
  228. : State(ExceptionSet)
  229. , Exception(std::move(exception))
  230. {
  231. }
  232. bool HasValue() const {
  233. return AtomicGet(State) == ValueSet;
  234. }
  235. void TryRethrow() const {
  236. TAtomicBase state = AtomicGet(State);
  237. TryRethrowWithState(state);
  238. }
  239. bool HasException() const {
  240. return AtomicGet(State) == ExceptionSet;
  241. }
  242. bool IsReady() const {
  243. return AtomicGet(State) != NotReady;
  244. }
  245. void GetValue(TDuration timeout = TDuration::Zero()) const {
  246. TAtomicBase state = AtomicGet(State);
  247. if (Y_UNLIKELY(state == NotReady)) {
  248. if (timeout == TDuration::Zero()) {
  249. ::NThreading::NImpl::ThrowFutureException("value not set"sv, __LOCATION__);
  250. }
  251. if (!Wait(timeout)) {
  252. ::NThreading::NImpl::ThrowFutureException("wait timeout"sv, __LOCATION__);
  253. }
  254. state = AtomicGet(State);
  255. }
  256. TryRethrowWithState(state);
  257. Y_ASSERT(state == ValueSet);
  258. }
  259. void SetValue() {
  260. bool success = TrySetValue();
  261. if (Y_UNLIKELY(!success)) {
  262. ::NThreading::NImpl::ThrowFutureException("value already set"sv, __LOCATION__);
  263. }
  264. }
  265. bool TrySetValue() {
  266. TSystemEvent* readyEvent = nullptr;
  267. TCallbackList<void> callbacks;
  268. with_lock (StateLock) {
  269. TAtomicBase state = AtomicGet(State);
  270. if (Y_UNLIKELY(state != NotReady)) {
  271. return false;
  272. }
  273. readyEvent = ReadyEvent.Get();
  274. callbacks = std::move(Callbacks);
  275. AtomicSet(State, ValueSet);
  276. }
  277. if (readyEvent) {
  278. readyEvent->Signal();
  279. }
  280. if (callbacks) {
  281. TFuture<void> temp(this);
  282. for (auto& callback : callbacks) {
  283. callback(temp);
  284. }
  285. }
  286. return true;
  287. }
  288. void SetException(std::exception_ptr e) {
  289. bool success = TrySetException(std::move(e));
  290. if (Y_UNLIKELY(!success)) {
  291. ::NThreading::NImpl::ThrowFutureException("value already set"sv, __LOCATION__);
  292. }
  293. }
  294. bool TrySetException(std::exception_ptr e) {
  295. TSystemEvent* readyEvent = nullptr;
  296. TCallbackList<void> callbacks;
  297. with_lock (StateLock) {
  298. TAtomicBase state = AtomicGet(State);
  299. if (Y_UNLIKELY(state != NotReady)) {
  300. return false;
  301. }
  302. Exception = std::move(e);
  303. readyEvent = ReadyEvent.Get();
  304. callbacks = std::move(Callbacks);
  305. AtomicSet(State, ExceptionSet);
  306. }
  307. if (readyEvent) {
  308. readyEvent->Signal();
  309. }
  310. if (callbacks) {
  311. TFuture<void> temp(this);
  312. for (auto& callback : callbacks) {
  313. callback(temp);
  314. }
  315. }
  316. return true;
  317. }
  318. template <typename F>
  319. bool Subscribe(F&& func) {
  320. with_lock (StateLock) {
  321. TAtomicBase state = AtomicGet(State);
  322. if (state == NotReady) {
  323. Callbacks.emplace_back(std::forward<F>(func));
  324. return true;
  325. }
  326. }
  327. return false;
  328. }
  329. void Wait() const {
  330. Wait(TInstant::Max());
  331. }
  332. bool Wait(TDuration timeout) const {
  333. return Wait(timeout.ToDeadLine());
  334. }
  335. bool Wait(TInstant deadline) const {
  336. TSystemEvent* readyEvent = nullptr;
  337. with_lock (StateLock) {
  338. TAtomicBase state = AtomicGet(State);
  339. if (state != NotReady) {
  340. return true;
  341. }
  342. if (!ReadyEvent) {
  343. ReadyEvent.Reset(new TSystemEvent());
  344. }
  345. readyEvent = ReadyEvent.Get();
  346. }
  347. Y_ASSERT(readyEvent);
  348. return readyEvent->WaitD(deadline);
  349. }
  350. void TryRethrowWithState(TAtomicBase state) const {
  351. if (Y_UNLIKELY(state == ExceptionSet)) {
  352. Y_ASSERT(Exception);
  353. std::rethrow_exception(Exception);
  354. }
  355. }
  356. };
  357. ////////////////////////////////////////////////////////////////////////////////
  358. template <typename T>
  359. inline void SetValueImpl(TPromise<T>& promise, const T& value) {
  360. promise.SetValue(value);
  361. }
  362. template <typename T>
  363. inline void SetValueImpl(TPromise<T>& promise, T&& value) {
  364. promise.SetValue(std::move(value));
  365. }
  366. template <typename T>
  367. inline void SetValueImpl(TPromise<T>& promise, const TFuture<T>& future,
  368. std::enable_if_t<!std::is_void<T>::value, bool> = false) {
  369. future.Subscribe([=](const TFuture<T>& f) mutable {
  370. T const* value;
  371. try {
  372. value = &f.GetValue();
  373. } catch (...) {
  374. promise.SetException(std::current_exception());
  375. return;
  376. }
  377. promise.SetValue(*value);
  378. });
  379. }
  380. template <typename T>
  381. inline void SetValueImpl(TPromise<void>& promise, const TFuture<T>& future) {
  382. future.Subscribe([=](const TFuture<T>& f) mutable {
  383. try {
  384. f.TryRethrow();
  385. } catch (...) {
  386. promise.SetException(std::current_exception());
  387. return;
  388. }
  389. promise.SetValue();
  390. });
  391. }
  392. template <typename T, typename F>
  393. inline void SetValue(TPromise<T>& promise, F&& func) {
  394. try {
  395. SetValueImpl(promise, func());
  396. } catch (...) {
  397. const bool success = promise.TrySetException(std::current_exception());
  398. if (Y_UNLIKELY(!success)) {
  399. throw;
  400. }
  401. }
  402. }
  403. template <typename F>
  404. inline void SetValue(TPromise<void>& promise, F&& func,
  405. std::enable_if_t<std::is_void<TFunctionResult<F>>::value, bool> = false) {
  406. try {
  407. func();
  408. } catch (...) {
  409. promise.SetException(std::current_exception());
  410. return;
  411. }
  412. promise.SetValue();
  413. }
  414. }
  415. ////////////////////////////////////////////////////////////////////////////////
  416. class TFutureStateId {
  417. private:
  418. const void* Id;
  419. public:
  420. template <typename T>
  421. explicit TFutureStateId(const NImpl::TFutureState<T>& state)
  422. : Id(&state)
  423. {
  424. }
  425. const void* Value() const noexcept {
  426. return Id;
  427. }
  428. };
  429. inline bool operator==(const TFutureStateId& l, const TFutureStateId& r) {
  430. return l.Value() == r.Value();
  431. }
  432. inline bool operator!=(const TFutureStateId& l, const TFutureStateId& r) {
  433. return !(l == r);
  434. }
  435. ////////////////////////////////////////////////////////////////////////////////
  436. template <typename T>
  437. inline TFuture<T>::TFuture(const TIntrusivePtr<TFutureState>& state) noexcept
  438. : State(state)
  439. {
  440. }
  441. template <typename T>
  442. inline void TFuture<T>::Swap(TFuture<T>& other) {
  443. State.Swap(other.State);
  444. }
  445. template <typename T>
  446. inline bool TFuture<T>::HasValue() const {
  447. return State && State->HasValue();
  448. }
  449. template <typename T>
  450. inline const T& TFuture<T>::GetValue(TDuration timeout) const {
  451. EnsureInitialized();
  452. return State->GetValue(timeout);
  453. }
  454. template <typename T>
  455. inline T TFuture<T>::ExtractValue(TDuration timeout) {
  456. EnsureInitialized();
  457. return State->ExtractValue(timeout);
  458. }
  459. template <typename T>
  460. inline const T& TFuture<T>::GetValueSync() const {
  461. return GetValue(TDuration::Max());
  462. }
  463. template <typename T>
  464. inline T TFuture<T>::ExtractValueSync() {
  465. return ExtractValue(TDuration::Max());
  466. }
  467. template <typename T>
  468. inline void TFuture<T>::TryRethrow() const {
  469. if (State) {
  470. State->TryRethrow();
  471. }
  472. }
  473. template <typename T>
  474. inline bool TFuture<T>::HasException() const {
  475. return State && State->HasException();
  476. }
  477. template <typename T>
  478. inline bool TFuture<T>::IsReady() const {
  479. return State && State->IsReady();
  480. }
  481. template <typename T>
  482. inline void TFuture<T>::Wait() const {
  483. EnsureInitialized();
  484. return State->Wait();
  485. }
  486. template <typename T>
  487. inline bool TFuture<T>::Wait(TDuration timeout) const {
  488. EnsureInitialized();
  489. return State->Wait(timeout);
  490. }
  491. template <typename T>
  492. inline bool TFuture<T>::Wait(TInstant deadline) const {
  493. EnsureInitialized();
  494. return State->Wait(deadline);
  495. }
  496. template <typename T>
  497. template <typename F>
  498. inline const TFuture<T>& TFuture<T>::Subscribe(F&& func) const {
  499. EnsureInitialized();
  500. if (!State->Subscribe(std::forward<F>(func))) {
  501. func(*this);
  502. }
  503. return *this;
  504. }
  505. template <typename T>
  506. template <typename F>
  507. inline const TFuture<T>& TFuture<T>::NoexceptSubscribe(F&& func) const noexcept {
  508. return Subscribe(std::forward<F>(func));
  509. }
  510. template <typename T>
  511. template <typename F>
  512. inline TFuture<TFutureType<TFutureCallResult<F, T>>> TFuture<T>::Apply(F&& func) const {
  513. auto promise = NewPromise<TFutureType<TFutureCallResult<F, T>>>();
  514. Subscribe([promise, func = std::forward<F>(func)](const TFuture<T>& future) mutable {
  515. NImpl::SetValue(promise, [&]() { return std::move(func)(future); });
  516. });
  517. return promise;
  518. }
  519. template <typename T>
  520. inline TFuture<void> TFuture<T>::IgnoreResult() const {
  521. auto promise = NewPromise();
  522. Subscribe([=](const TFuture<T>& future) mutable {
  523. NImpl::SetValueImpl(promise, future);
  524. });
  525. return promise;
  526. }
  527. template <typename T>
  528. inline bool TFuture<T>::Initialized() const {
  529. return bool(State);
  530. }
  531. template <typename T>
  532. inline TMaybe<TFutureStateId> TFuture<T>::StateId() const noexcept {
  533. return State != nullptr ? MakeMaybe<TFutureStateId>(*State) : Nothing();
  534. }
  535. template <typename T>
  536. inline void TFuture<T>::EnsureInitialized() const {
  537. if (!State) {
  538. ::NThreading::NImpl::ThrowFutureException("state not initialized"sv, __LOCATION__);
  539. }
  540. }
  541. ////////////////////////////////////////////////////////////////////////////////
  542. inline TFuture<void>::TFuture(const TIntrusivePtr<TFutureState>& state) noexcept
  543. : State(state)
  544. {
  545. }
  546. inline void TFuture<void>::Swap(TFuture<void>& other) {
  547. State.Swap(other.State);
  548. }
  549. inline bool TFuture<void>::HasValue() const {
  550. return State && State->HasValue();
  551. }
  552. inline void TFuture<void>::GetValue(TDuration timeout) const {
  553. EnsureInitialized();
  554. State->GetValue(timeout);
  555. }
  556. inline void TFuture<void>::GetValueSync() const {
  557. GetValue(TDuration::Max());
  558. }
  559. inline void TFuture<void>::TryRethrow() const {
  560. if (State) {
  561. State->TryRethrow();
  562. }
  563. }
  564. inline bool TFuture<void>::HasException() const {
  565. return State && State->HasException();
  566. }
  567. inline bool TFuture<void>::IsReady() const {
  568. return State && State->IsReady();
  569. }
  570. inline void TFuture<void>::Wait() const {
  571. EnsureInitialized();
  572. return State->Wait();
  573. }
  574. inline bool TFuture<void>::Wait(TDuration timeout) const {
  575. EnsureInitialized();
  576. return State->Wait(timeout);
  577. }
  578. inline bool TFuture<void>::Wait(TInstant deadline) const {
  579. EnsureInitialized();
  580. return State->Wait(deadline);
  581. }
  582. template <typename F>
  583. inline const TFuture<void>& TFuture<void>::Subscribe(F&& func) const {
  584. EnsureInitialized();
  585. if (!State->Subscribe(std::forward<F>(func))) {
  586. func(*this);
  587. }
  588. return *this;
  589. }
  590. template <typename F>
  591. inline const TFuture<void>& TFuture<void>::NoexceptSubscribe(F&& func) const noexcept {
  592. return Subscribe(std::forward<F>(func));
  593. }
  594. template <typename F>
  595. inline TFuture<TFutureType<TFutureCallResult<F, void>>> TFuture<void>::Apply(F&& func) const {
  596. auto promise = NewPromise<TFutureType<TFutureCallResult<F, void>>>();
  597. Subscribe([promise, func = std::forward<F>(func)](const TFuture<void>& future) mutable {
  598. NImpl::SetValue(promise, [&]() { return std::move(func)(future); });
  599. });
  600. return promise;
  601. }
  602. template <typename R>
  603. inline TFuture<std::remove_cvref_t<R>> TFuture<void>::Return(R&& value) const {
  604. auto promise = NewPromise<std::remove_cvref_t<R>>();
  605. Subscribe([promise, value = std::forward<R>(value)](const TFuture<void>& future) mutable {
  606. try {
  607. future.TryRethrow();
  608. } catch (...) {
  609. promise.SetException(std::current_exception());
  610. return;
  611. }
  612. promise.SetValue(std::move(value));
  613. });
  614. return promise;
  615. }
  616. inline bool TFuture<void>::Initialized() const {
  617. return bool(State);
  618. }
  619. inline TMaybe<TFutureStateId> TFuture<void>::StateId() const noexcept {
  620. return State != nullptr ? MakeMaybe<TFutureStateId>(*State) : Nothing();
  621. }
  622. inline void TFuture<void>::EnsureInitialized() const {
  623. if (!State) {
  624. ::NThreading::NImpl::ThrowFutureException("state not initialized"sv, __LOCATION__);
  625. }
  626. }
  627. ////////////////////////////////////////////////////////////////////////////////
  628. template <typename T>
  629. inline TPromise<T>::TPromise(const TIntrusivePtr<TFutureState>& state) noexcept
  630. : State(state)
  631. {
  632. }
  633. template <typename T>
  634. inline void TPromise<T>::Swap(TPromise<T>& other) {
  635. State.Swap(other.State);
  636. }
  637. template <typename T>
  638. inline const T& TPromise<T>::GetValue() const {
  639. EnsureInitialized();
  640. return State->GetValue();
  641. }
  642. template <typename T>
  643. inline T TPromise<T>::ExtractValue() {
  644. EnsureInitialized();
  645. return State->ExtractValue();
  646. }
  647. template <typename T>
  648. inline bool TPromise<T>::HasValue() const {
  649. return State && State->HasValue();
  650. }
  651. template <typename T>
  652. inline void TPromise<T>::SetValue(const T& value) {
  653. EnsureInitialized();
  654. State->SetValue(value);
  655. }
  656. template <typename T>
  657. inline void TPromise<T>::SetValue(T&& value) {
  658. EnsureInitialized();
  659. State->SetValue(std::move(value));
  660. }
  661. template <typename T>
  662. inline bool TPromise<T>::TrySetValue(const T& value) {
  663. EnsureInitialized();
  664. return State->TrySetValue(value);
  665. }
  666. template <typename T>
  667. inline bool TPromise<T>::TrySetValue(T&& value) {
  668. EnsureInitialized();
  669. return State->TrySetValue(std::move(value));
  670. }
  671. template <typename T>
  672. inline void TPromise<T>::TryRethrow() const {
  673. if (State) {
  674. State->TryRethrow();
  675. }
  676. }
  677. template <typename T>
  678. inline bool TPromise<T>::HasException() const {
  679. return State && State->HasException();
  680. }
  681. template <typename T>
  682. inline bool TPromise<T>::IsReady() const {
  683. return State && State->IsReady();
  684. }
  685. template <typename T>
  686. inline void TPromise<T>::SetException(const TString& e) {
  687. EnsureInitialized();
  688. State->SetException(std::make_exception_ptr(yexception() << e));
  689. }
  690. template <typename T>
  691. inline void TPromise<T>::SetException(std::exception_ptr e) {
  692. EnsureInitialized();
  693. State->SetException(std::move(e));
  694. }
  695. template <typename T>
  696. inline bool TPromise<T>::TrySetException(std::exception_ptr e) {
  697. EnsureInitialized();
  698. return State->TrySetException(std::move(e));
  699. }
  700. template <typename T>
  701. inline TFuture<T> TPromise<T>::GetFuture() const {
  702. EnsureInitialized();
  703. return TFuture<T>(State);
  704. }
  705. template <typename T>
  706. inline TPromise<T>::operator TFuture<T>() const {
  707. return GetFuture();
  708. }
  709. template <typename T>
  710. inline bool TPromise<T>::Initialized() const {
  711. return bool(State);
  712. }
  713. template <typename T>
  714. inline void TPromise<T>::EnsureInitialized() const {
  715. if (!State) {
  716. ::NThreading::NImpl::ThrowFutureException("state not initialized"sv, __LOCATION__);
  717. }
  718. }
  719. ////////////////////////////////////////////////////////////////////////////////
  720. inline TPromise<void>::TPromise(const TIntrusivePtr<TFutureState>& state) noexcept
  721. : State(state)
  722. {
  723. }
  724. inline void TPromise<void>::Swap(TPromise<void>& other) {
  725. State.Swap(other.State);
  726. }
  727. inline void TPromise<void>::GetValue() const {
  728. EnsureInitialized();
  729. State->GetValue();
  730. }
  731. inline bool TPromise<void>::HasValue() const {
  732. return State && State->HasValue();
  733. }
  734. inline void TPromise<void>::SetValue() {
  735. EnsureInitialized();
  736. State->SetValue();
  737. }
  738. inline bool TPromise<void>::TrySetValue() {
  739. EnsureInitialized();
  740. return State->TrySetValue();
  741. }
  742. inline void TPromise<void>::TryRethrow() const {
  743. if(State) {
  744. State->TryRethrow();
  745. }
  746. }
  747. inline bool TPromise<void>::HasException() const {
  748. return State && State->HasException();
  749. }
  750. inline bool TPromise<void>::IsReady() const {
  751. return State && State->IsReady();
  752. }
  753. inline void TPromise<void>::SetException(const TString& e) {
  754. EnsureInitialized();
  755. State->SetException(std::make_exception_ptr(yexception() << e));
  756. }
  757. inline void TPromise<void>::SetException(std::exception_ptr e) {
  758. EnsureInitialized();
  759. State->SetException(std::move(e));
  760. }
  761. inline bool TPromise<void>::TrySetException(std::exception_ptr e) {
  762. EnsureInitialized();
  763. return State->TrySetException(std::move(e));
  764. }
  765. inline TFuture<void> TPromise<void>::GetFuture() const {
  766. EnsureInitialized();
  767. return TFuture<void>(State);
  768. }
  769. inline TPromise<void>::operator TFuture<void>() const {
  770. return GetFuture();
  771. }
  772. inline bool TPromise<void>::Initialized() const {
  773. return bool(State);
  774. }
  775. inline void TPromise<void>::EnsureInitialized() const {
  776. if (!State) {
  777. ::NThreading::NImpl::ThrowFutureException("state not initialized"sv, __LOCATION__);
  778. }
  779. }
  780. ////////////////////////////////////////////////////////////////////////////////
  781. template <typename T>
  782. inline TPromise<T> NewPromise() {
  783. return {new NImpl::TFutureState<T>()};
  784. }
  785. inline TPromise<void> NewPromise() {
  786. return {new NImpl::TFutureState<void>()};
  787. }
  788. template <typename T>
  789. inline TFuture<T> MakeFuture(const T& value) {
  790. return {new NImpl::TFutureState<T>(value)};
  791. }
  792. template <typename T>
  793. inline TFuture<std::remove_reference_t<T>> MakeFuture(T&& value) {
  794. return {new NImpl::TFutureState<std::remove_reference_t<T>>(std::forward<T>(value))};
  795. }
  796. template <typename T>
  797. inline TFuture<T> MakeFuture() {
  798. struct TCache {
  799. TFuture<T> Instance{new NImpl::TFutureState<T>(Default<T>())};
  800. TCache() {
  801. // Immediately advance state from ValueSet to ValueRead.
  802. // This should prevent corrupting shared value with an ExtractValue() call.
  803. Y_UNUSED(Instance.GetValue());
  804. }
  805. };
  806. return Singleton<TCache>()->Instance;
  807. }
  808. template <typename T>
  809. inline TFuture<T> MakeErrorFuture(std::exception_ptr exception)
  810. {
  811. return {new NImpl::TFutureState<T>(std::move(exception), NImpl::TError::Error)};
  812. }
  813. inline TFuture<void> MakeFuture() {
  814. struct TCache {
  815. TFuture<void> Instance{new NImpl::TFutureState<void>(true)};
  816. };
  817. return Singleton<TCache>()->Instance;
  818. }
  819. }