future-inl.h 29 KB

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