future-inl.h 28 KB

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