WwiseFuture.h 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #pragma once
  16. #include "CoreTypes.h"
  17. #include "Misc/AssertionMacros.h"
  18. #include "Templates/UnrealTemplate.h"
  19. #include "Templates/Function.h"
  20. #include "Misc/Timespan.h"
  21. #include "Templates/SharedPointer.h"
  22. #include "Misc/DateTime.h"
  23. #include "HAL/Event.h"
  24. #include "Wwise/Stats/Concurrency.h"
  25. #include "Wwise/Stats/AsyncStats.h"
  26. #include <atomic>
  27. //
  28. // WwiseFuture is a replica of Unreal's Async/Future.h code, with optimizations on the FutureState to reduce the
  29. // amount of FCriticalSection and FEvent to the bare minimum. Most of Wwise Integrations code uses the "Then" paradigm
  30. // of Futures/Promises instead of the Wait paradigm.
  31. //
  32. /**
  33. * Base class for the internal state of asynchronous return values (futures).
  34. */
  35. class FWwiseFutureState
  36. {
  37. public:
  38. /** Default constructor. */
  39. FWwiseFutureState()
  40. : CompletionCallback(nullptr)
  41. , Complete(false)
  42. {
  43. ASYNC_INC_DWORD_STAT(STAT_WwiseFutures);
  44. }
  45. /**
  46. * Create and initialize a new instance with a callback.
  47. *
  48. * @param InCompletionCallback A function that is called when the state is completed.
  49. */
  50. FWwiseFutureState(TUniqueFunction<void()>&& InCompletionCallback)
  51. : CompletionCallback(InCompletionCallback ? new TUniqueFunction<void()>(MoveTemp(InCompletionCallback)) : nullptr)
  52. , Complete(false)
  53. {
  54. ASYNC_INC_DWORD_STAT(STAT_WwiseFutures);
  55. }
  56. /** Destructor. */
  57. ~FWwiseFutureState()
  58. {
  59. const auto* Continuation = CompletionCallback.exchange(nullptr);
  60. check(!Continuation);
  61. if (UNLIKELY(Continuation))
  62. {
  63. delete Continuation;
  64. }
  65. ASYNC_DEC_DWORD_STAT(STAT_WwiseFutures);
  66. }
  67. public:
  68. /**
  69. * Checks whether the asynchronous result has been set.
  70. *
  71. * @return true if the result has been set, false otherwise.
  72. * @see WaitFor
  73. */
  74. bool IsComplete() const
  75. {
  76. return Complete.load(std::memory_order_seq_cst);
  77. }
  78. /**
  79. * Blocks the calling thread until the future result is available.
  80. *
  81. * Compared to Unreal's native version, this version uses continuation, and assumes you haven't set a continuation
  82. * function on this state.
  83. *
  84. * @param Duration The maximum time span to wait for the future result.
  85. * @return true if the result is available, false otherwise.
  86. * @see IsComplete
  87. */
  88. bool WaitFor(const FTimespan& Duration)
  89. {
  90. check(!CompletionCallback.load(std::memory_order_seq_cst));
  91. if (IsComplete())
  92. {
  93. return true;
  94. }
  95. auto CompletionEvent = MakeShared<FEventRef, ESPMode::ThreadSafe>();
  96. SetContinuation([CompletionEvent]
  97. {
  98. CompletionEvent.Get()->Trigger();
  99. });
  100. return CompletionEvent.Get()->Wait(Duration);
  101. }
  102. /**
  103. * Set a continuation to be called on completion of the promise
  104. * @param Continuation
  105. */
  106. void SetContinuation(TUniqueFunction<void()>&& Continuation)
  107. {
  108. if (IsComplete())
  109. {
  110. if (Continuation)
  111. {
  112. Continuation();
  113. }
  114. return;
  115. }
  116. // Store the Copy to the CompletionCallback
  117. auto Copy = Continuation ? new TUniqueFunction<void()>(MoveTemp(Continuation)) : nullptr;
  118. auto OldCopy = CompletionCallback.exchange(Copy);
  119. check(!OldCopy); // We can only execute one continuation per WwiseFuture.
  120. if (!IsComplete())
  121. {
  122. return;
  123. }
  124. // We are already complete. See if we need to execute ourselves.
  125. Copy = CompletionCallback.exchange(nullptr);
  126. if (Copy)
  127. {
  128. (*Copy)();
  129. delete Copy;
  130. }
  131. }
  132. protected:
  133. /** Notifies any waiting threads that the result is available. */
  134. void MarkComplete()
  135. {
  136. Complete.store(true, std::memory_order_seq_cst);
  137. auto* Continuation = CompletionCallback.exchange(nullptr);
  138. if (Continuation)
  139. {
  140. (*Continuation)();
  141. delete Continuation;
  142. }
  143. }
  144. private:
  145. /** An optional callback function that is executed the state is completed. */
  146. std::atomic< TUniqueFunction<void()>* > CompletionCallback;
  147. /** Whether the asynchronous result is available. */
  148. std::atomic<bool> Complete;
  149. };
  150. /**
  151. * Implements the internal state of asynchronous return values (futures).
  152. */
  153. template<typename InternalResultType>
  154. class TWwiseFutureState
  155. : public FWwiseFutureState
  156. {
  157. public:
  158. /** Default constructor. */
  159. TWwiseFutureState()
  160. : FWwiseFutureState()
  161. { }
  162. ~TWwiseFutureState()
  163. {
  164. if (IsComplete())
  165. {
  166. DestructItem(Result.GetTypedPtr());
  167. }
  168. }
  169. /**
  170. * Create and initialize a new instance with a callback.
  171. *
  172. * @param CompletionCallback A function that is called when the state is completed.
  173. */
  174. TWwiseFutureState(TUniqueFunction<void()>&& CompletionCallback)
  175. : FWwiseFutureState(MoveTemp(CompletionCallback))
  176. { }
  177. public:
  178. /**
  179. * Gets the result (will block the calling thread until the result is available).
  180. *
  181. * @return The result value.
  182. * @see EmplaceResult
  183. */
  184. const InternalResultType& GetResult()
  185. {
  186. while (!IsComplete())
  187. {
  188. WaitFor(FTimespan::MaxValue());
  189. }
  190. return *Result.GetTypedPtr();
  191. }
  192. /**
  193. * Sets the result and notifies any waiting threads.
  194. *
  195. * @param InResult The result to set.
  196. * @see GetResult
  197. */
  198. template<typename... ArgTypes>
  199. void EmplaceResult(ArgTypes&&... Args)
  200. {
  201. check(!IsComplete());
  202. new(Result.GetTypedPtr()) InternalResultType(Forward<ArgTypes>(Args)...);
  203. MarkComplete();
  204. }
  205. private:
  206. /** Holds the asynchronous result. */
  207. TTypeCompatibleBytes<InternalResultType> Result;
  208. };
  209. /* TWwiseFuture
  210. *****************************************************************************/
  211. /**
  212. * Abstract base template for futures and shared futures.
  213. */
  214. template<typename InternalResultType>
  215. class TWwiseFutureBase
  216. {
  217. public:
  218. /**
  219. * Checks whether this future object has its value set.
  220. *
  221. * @return true if this future has a shared state and the value has been set, false otherwise.
  222. * @see IsValid
  223. */
  224. bool IsReady() const
  225. {
  226. return State.IsValid() ? State->IsComplete() : false;
  227. }
  228. /**
  229. * Checks whether this future object has a valid state.
  230. *
  231. * @return true if the state is valid, false otherwise.
  232. * @see IsReady
  233. */
  234. bool IsValid() const
  235. {
  236. return State.IsValid();
  237. }
  238. /**
  239. * Blocks the calling thread until the future result is available.
  240. *
  241. * Note that this method may block forever if the result is never set. Use
  242. * the WaitFor or WaitUntil methods to specify a maximum timeout for the wait.
  243. *
  244. * @see WaitFor, WaitUntil
  245. */
  246. void Wait() const
  247. {
  248. if (State.IsValid())
  249. {
  250. while (!WaitFor(FTimespan::MaxValue()));
  251. }
  252. }
  253. /**
  254. * Blocks the calling thread until the future result is available or the specified duration is exceeded.
  255. *
  256. * @param Duration The maximum time span to wait for the future result.
  257. * @return true if the result is available, false otherwise.
  258. * @see Wait, WaitUntil
  259. */
  260. bool WaitFor(const FTimespan& Duration) const
  261. {
  262. return State.IsValid() ? State->WaitFor(Duration) : false;
  263. }
  264. /**
  265. * Blocks the calling thread until the future result is available or the specified time is hit.
  266. *
  267. * @param Time The time until to wait for the future result (in UTC).
  268. * @return true if the result is available, false otherwise.
  269. * @see Wait, WaitUntil
  270. */
  271. bool WaitUntil(const FDateTime& Time) const
  272. {
  273. return WaitFor(Time - FDateTime::UtcNow());
  274. }
  275. protected:
  276. typedef TSharedPtr<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe> StateType;
  277. /** Default constructor. */
  278. TWwiseFutureBase() { }
  279. /**
  280. * Creates and initializes a new instance.
  281. *
  282. * @param InState The shared state to initialize with.
  283. */
  284. TWwiseFutureBase(const StateType& InState)
  285. : State(InState)
  286. { }
  287. /**
  288. * Protected move construction
  289. */
  290. TWwiseFutureBase(TWwiseFutureBase&&) = default;
  291. /**
  292. * Protected move assignment
  293. */
  294. TWwiseFutureBase& operator=(TWwiseFutureBase&&) = default;
  295. /**
  296. * Protected copy construction
  297. */
  298. TWwiseFutureBase(const TWwiseFutureBase&) = default;
  299. /**
  300. * Protected copy assignment
  301. */
  302. TWwiseFutureBase& operator=(const TWwiseFutureBase&) = default;
  303. /** Protected destructor. */
  304. ~TWwiseFutureBase() { }
  305. protected:
  306. /**
  307. * Gets the shared state object.
  308. *
  309. * @return The shared state object.
  310. */
  311. const StateType& GetState() const
  312. {
  313. // if you hit this assertion then your future has an invalid state.
  314. // this happens if you have an uninitialized future or if you moved
  315. // it to another instance.
  316. check(State.IsValid());
  317. return State;
  318. }
  319. /**
  320. * Set a completion callback that will be called once the future completes
  321. * or immediately if already completed
  322. *
  323. * @param Continuation a continuation taking an argument of type TWwiseFuture<InternalResultType>
  324. * @return nothing at the moment but could return another future to allow future chaining
  325. */
  326. template<typename Func>
  327. auto Then(Func Continuation);
  328. /**
  329. * Convenience wrapper for Then that
  330. * set a completion callback that will be called once the future completes
  331. * or immediately if already completed
  332. * @param Continuation a continuation taking an argument of type InternalResultType
  333. * @return nothing at the moment but could return another future to allow future chaining
  334. */
  335. template<typename Func>
  336. auto Next(Func Continuation);
  337. /**
  338. * Reset the future.
  339. * Resetting a future removes any continuation from its shared state and invalidates it.
  340. * Useful for discarding yet to be completed future cleanly.
  341. */
  342. void Reset()
  343. {
  344. if (IsValid())
  345. {
  346. this->State->SetContinuation(nullptr);
  347. this->State.Reset();
  348. }
  349. }
  350. private:
  351. /** Holds the future's state. */
  352. StateType State;
  353. };
  354. /**
  355. * Template for unshared futures.
  356. */
  357. template<typename ResultType>
  358. class TWwiseFuture
  359. : public TWwiseFutureBase<ResultType>
  360. {
  361. typedef TWwiseFutureBase<ResultType> BaseType;
  362. public:
  363. /** Default constructor. */
  364. TWwiseFuture() { }
  365. /**
  366. * Creates and initializes a new instance.
  367. *
  368. * @param InState The shared state to initialize with.
  369. */
  370. TWwiseFuture(const typename BaseType::StateType& InState)
  371. : BaseType(InState)
  372. { }
  373. /**
  374. * Move constructor.
  375. */
  376. TWwiseFuture(TWwiseFuture&&) = default;
  377. /**
  378. * Move assignment operator.
  379. */
  380. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  381. /** Destructor. */
  382. ~TWwiseFuture() { }
  383. public:
  384. /**
  385. * Gets the future's result.
  386. *
  387. * @return The result.
  388. */
  389. ResultType Get() const
  390. {
  391. return this->GetState()->GetResult();
  392. }
  393. /**
  394. * Expose Then functionality
  395. * @see TWwiseFutureBase
  396. */
  397. using BaseType::Then;
  398. /**
  399. * Expose Next functionality
  400. * @see TWwiseFutureBase
  401. */
  402. using BaseType::Next;
  403. /**
  404. * Expose Reset functionality
  405. * @see TWwiseFutureBase
  406. */
  407. using BaseType::Reset;
  408. private:
  409. /** Hidden copy constructor (futures cannot be copied). */
  410. TWwiseFuture(const TWwiseFuture&);
  411. /** Hidden copy assignment (futures cannot be copied). */
  412. TWwiseFuture& operator=(const TWwiseFuture&);
  413. };
  414. /**
  415. * Template for unshared futures (specialization for reference types).
  416. */
  417. template<typename ResultType>
  418. class TWwiseFuture<ResultType&>
  419. : public TWwiseFutureBase<ResultType*>
  420. {
  421. typedef TWwiseFutureBase<ResultType*> BaseType;
  422. public:
  423. /** Default constructor. */
  424. TWwiseFuture() { }
  425. /**
  426. * Creates and initializes a new instance.
  427. *
  428. * @param InState The shared state to initialize with.
  429. */
  430. TWwiseFuture(const typename BaseType::StateType& InState)
  431. : BaseType(InState)
  432. { }
  433. /**
  434. * Move constructor.
  435. */
  436. TWwiseFuture(TWwiseFuture&&) = default;
  437. /**
  438. * Move assignment operator.
  439. */
  440. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  441. /** Destructor. */
  442. ~TWwiseFuture() { }
  443. public:
  444. /**
  445. * Gets the future's result.
  446. *
  447. * @return The result.
  448. */
  449. ResultType& Get() const
  450. {
  451. return *this->GetState()->GetResult();
  452. }
  453. /**
  454. * Expose Then functionality
  455. * @see TWwiseFutureBase
  456. */
  457. using BaseType::Then;
  458. /**
  459. * Expose Next functionality
  460. * @see TWwiseFutureBase
  461. */
  462. using BaseType::Next;
  463. /**
  464. * Expose Reset functionality
  465. * @see TWwiseFutureBase
  466. */
  467. using BaseType::Reset;
  468. private:
  469. /** Hidden copy constructor (futures cannot be copied). */
  470. TWwiseFuture(const TWwiseFuture&);
  471. /** Hidden copy assignment (futures cannot be copied). */
  472. TWwiseFuture& operator=(const TWwiseFuture&);
  473. };
  474. /**
  475. * Template for unshared futures (specialization for void).
  476. */
  477. template<>
  478. class TWwiseFuture<void>
  479. : public TWwiseFutureBase<int>
  480. {
  481. typedef TWwiseFutureBase<int> BaseType;
  482. public:
  483. /** Default constructor. */
  484. TWwiseFuture() { }
  485. /**
  486. * Creates and initializes a new instance.
  487. *
  488. * @param InState The shared state to initialize with.
  489. */
  490. TWwiseFuture(const BaseType::StateType& InState)
  491. : BaseType(InState)
  492. { }
  493. /**
  494. * Move constructor.
  495. */
  496. TWwiseFuture(TWwiseFuture&&) = default;
  497. /**
  498. * Move assignment operator.
  499. */
  500. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  501. /** Destructor. */
  502. ~TWwiseFuture() { }
  503. public:
  504. /**
  505. * Gets the future's result.
  506. *
  507. * @return The result.
  508. */
  509. void Get() const
  510. {
  511. GetState()->GetResult();
  512. }
  513. /**
  514. * Expose Then functionality
  515. * @see TWwiseFutureBase
  516. */
  517. using BaseType::Then;
  518. /**
  519. * Expose Next functionality
  520. * @see TWwiseFutureBase
  521. */
  522. using BaseType::Next;
  523. /**
  524. * Expose Reset functionality
  525. * @see TWwiseFutureBase
  526. */
  527. using BaseType::Reset;
  528. private:
  529. /** Hidden copy constructor (futures cannot be copied). */
  530. TWwiseFuture(const TWwiseFuture&);
  531. /** Hidden copy assignment (futures cannot be copied). */
  532. TWwiseFuture& operator=(const TWwiseFuture&);
  533. };
  534. /* TWwisePromise
  535. *****************************************************************************/
  536. template<typename InternalResultType>
  537. class TWwisePromiseBase
  538. : FNoncopyable
  539. {
  540. typedef TSharedPtr<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe> StateType;
  541. public:
  542. /** Default constructor. */
  543. TWwisePromiseBase()
  544. : State(MakeShared<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe>())
  545. { }
  546. /**
  547. * Move constructor.
  548. *
  549. * @param Other The promise holding the shared state to move.
  550. */
  551. TWwisePromiseBase(TWwisePromiseBase&& Other)
  552. : State(MoveTemp(Other.State))
  553. {
  554. Other.State.Reset();
  555. }
  556. /**
  557. * Create and initialize a new instance with a callback.
  558. *
  559. * @param CompletionCallback A function that is called when the future state is completed.
  560. */
  561. TWwisePromiseBase(TUniqueFunction<void()>&& CompletionCallback)
  562. : State(MakeShared<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe>(MoveTemp(CompletionCallback)))
  563. { }
  564. public:
  565. /** Move assignment operator. */
  566. TWwisePromiseBase& operator=(TWwisePromiseBase&& Other)
  567. {
  568. State = Other.State;
  569. Other.State.Reset();
  570. return *this;
  571. }
  572. protected:
  573. /** Destructor. */
  574. ~TWwisePromiseBase()
  575. {
  576. if (State.IsValid())
  577. {
  578. // if you hit this assertion then your promise never had its result
  579. // value set. broken promises are considered programming errors.
  580. check(State->IsComplete());
  581. State.Reset();
  582. }
  583. }
  584. /**
  585. * Gets the shared state object.
  586. *
  587. * @return The shared state object.
  588. */
  589. const StateType& GetState()
  590. {
  591. // if you hit this assertion then your promise has an invalid state.
  592. // this happens if you move the promise to another instance.
  593. check(State.IsValid());
  594. return State;
  595. }
  596. private:
  597. /** Holds the shared state object. */
  598. StateType State;
  599. };
  600. /**
  601. * Template for promises.
  602. */
  603. template<typename ResultType>
  604. class TWwisePromise
  605. : public TWwisePromiseBase<ResultType>
  606. {
  607. public:
  608. typedef TWwisePromiseBase<ResultType> BaseType;
  609. /** Default constructor (creates a new shared state). */
  610. TWwisePromise()
  611. : BaseType()
  612. , FutureRetrieved(false)
  613. { }
  614. /**
  615. * Move constructor.
  616. *
  617. * @param Other The promise holding the shared state to move.
  618. */
  619. TWwisePromise(TWwisePromise&& Other)
  620. : BaseType(MoveTemp(Other))
  621. , FutureRetrieved(MoveTemp(Other.FutureRetrieved))
  622. { }
  623. /**
  624. * Create and initialize a new instance with a callback.
  625. *
  626. * @param CompletionCallback A function that is called when the future state is completed.
  627. */
  628. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  629. : BaseType(MoveTemp(CompletionCallback))
  630. , FutureRetrieved(false)
  631. { }
  632. public:
  633. /**
  634. * Move assignment operator.
  635. *
  636. * @param Other The promise holding the shared state to move.
  637. */
  638. TWwisePromise& operator=(TWwisePromise&& Other)
  639. {
  640. BaseType::operator=(MoveTemp(Other));
  641. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  642. return *this;
  643. }
  644. public:
  645. /**
  646. * Gets a TWwiseFuture object associated with the shared state of this promise.
  647. *
  648. * @return The TWwiseFuture object.
  649. */
  650. TWwiseFuture<ResultType> GetFuture()
  651. {
  652. check(!FutureRetrieved);
  653. FutureRetrieved = true;
  654. return TWwiseFuture<ResultType>(this->GetState());
  655. }
  656. /**
  657. * Sets the promised result.
  658. *
  659. * The result must be set only once. An assertion will
  660. * be triggered if this method is called a second time.
  661. *
  662. * @param Result The result value to set.
  663. */
  664. FORCEINLINE void SetValue(const ResultType& Result)
  665. {
  666. EmplaceValue(Result);
  667. }
  668. /**
  669. * Sets the promised result (from rvalue).
  670. *
  671. * The result must be set only once. An assertion will
  672. * be triggered if this method is called a second time.
  673. *
  674. * @param Result The result value to set.
  675. */
  676. FORCEINLINE void SetValue(ResultType&& Result)
  677. {
  678. EmplaceValue(MoveTemp(Result));
  679. }
  680. /**
  681. * Sets the promised result.
  682. *
  683. * The result must be set only once. An assertion will
  684. * be triggered if this method is called a second time.
  685. *
  686. * @param Result The result value to set.
  687. */
  688. template<typename... ArgTypes>
  689. void EmplaceValue(ArgTypes&&... Args)
  690. {
  691. this->GetState()->EmplaceResult(Forward<ArgTypes>(Args)...);
  692. }
  693. private:
  694. /** Whether a future has already been retrieved from this promise. */
  695. bool FutureRetrieved;
  696. };
  697. /**
  698. * Template for promises (specialization for reference types).
  699. */
  700. template<typename ResultType>
  701. class TWwisePromise<ResultType&>
  702. : public TWwisePromiseBase<ResultType*>
  703. {
  704. typedef TWwisePromiseBase<ResultType*> BaseType;
  705. public:
  706. /** Default constructor (creates a new shared state). */
  707. TWwisePromise()
  708. : BaseType()
  709. , FutureRetrieved(false)
  710. { }
  711. /**
  712. * Move constructor.
  713. *
  714. * @param Other The promise holding the shared state to move.
  715. */
  716. TWwisePromise(TWwisePromise&& Other)
  717. : BaseType(MoveTemp(Other))
  718. , FutureRetrieved(MoveTemp(Other.FutureRetrieved))
  719. { }
  720. /**
  721. * Create and initialize a new instance with a callback.
  722. *
  723. * @param CompletionCallback A function that is called when the future state is completed.
  724. */
  725. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  726. : BaseType(MoveTemp(CompletionCallback))
  727. , FutureRetrieved(false)
  728. { }
  729. public:
  730. /**
  731. * Move assignment operator.
  732. *
  733. * @param Other The promise holding the shared state to move.
  734. */
  735. TWwisePromise& operator=(TWwisePromise&& Other)
  736. {
  737. BaseType::operator=(MoveTemp(Other));
  738. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  739. return this;
  740. }
  741. public:
  742. /**
  743. * Gets a TWwiseFuture object associated with the shared state of this promise.
  744. *
  745. * @return The TWwiseFuture object.
  746. */
  747. TWwiseFuture<ResultType&> GetFuture()
  748. {
  749. check(!FutureRetrieved);
  750. FutureRetrieved = true;
  751. return TWwiseFuture<ResultType&>(this->GetState());
  752. }
  753. /**
  754. * Sets the promised result.
  755. *
  756. * The result must be set only once. An assertion will
  757. * be triggered if this method is called a second time.
  758. *
  759. * @param Result The result value to set.
  760. */
  761. FORCEINLINE void SetValue(ResultType& Result)
  762. {
  763. EmplaceValue(Result);
  764. }
  765. /**
  766. * Sets the promised result.
  767. *
  768. * The result must be set only once. An assertion will
  769. * be triggered if this method is called a second time.
  770. *
  771. * @param Result The result value to set.
  772. */
  773. void EmplaceValue(ResultType& Result)
  774. {
  775. this->GetState()->EmplaceResult(&Result);
  776. }
  777. private:
  778. /** Whether a future has already been retrieved from this promise. */
  779. bool FutureRetrieved;
  780. };
  781. /**
  782. * Template for promises (specialization for void results).
  783. */
  784. template<>
  785. class TWwisePromise<void>
  786. : public TWwisePromiseBase<int>
  787. {
  788. typedef TWwisePromiseBase<int> BaseType;
  789. public:
  790. /** Default constructor (creates a new shared state). */
  791. TWwisePromise()
  792. : BaseType()
  793. , FutureRetrieved(false)
  794. { }
  795. /**
  796. * Move constructor.
  797. *
  798. * @param Other The promise holding the shared state to move.
  799. */
  800. TWwisePromise(TWwisePromise&& Other)
  801. : BaseType(MoveTemp(Other))
  802. , FutureRetrieved(false)
  803. { }
  804. /**
  805. * Create and initialize a new instance with a callback.
  806. *
  807. * @param CompletionCallback A function that is called when the future state is completed.
  808. */
  809. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  810. : BaseType(MoveTemp(CompletionCallback))
  811. , FutureRetrieved(false)
  812. { }
  813. public:
  814. /**
  815. * Move assignment operator.
  816. *
  817. * @param Other The promise holding the shared state to move.
  818. */
  819. TWwisePromise& operator=(TWwisePromise&& Other)
  820. {
  821. BaseType::operator=(MoveTemp(Other));
  822. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  823. return *this;
  824. }
  825. public:
  826. /**
  827. * Gets a TWwiseFuture object associated with the shared state of this promise.
  828. *
  829. * @return The TWwiseFuture object.
  830. */
  831. TWwiseFuture<void> GetFuture()
  832. {
  833. check(!FutureRetrieved);
  834. FutureRetrieved = true;
  835. return TWwiseFuture<void>(GetState());
  836. }
  837. /**
  838. * Sets the promised result.
  839. *
  840. * The result must be set only once. An assertion will
  841. * be triggered if this method is called a second time.
  842. */
  843. FORCEINLINE void SetValue()
  844. {
  845. EmplaceValue();
  846. }
  847. /**
  848. * Sets the promised result.
  849. *
  850. * The result must be set only once. An assertion will
  851. * be triggered if this method is called a second time.
  852. *
  853. * @param Result The result value to set.
  854. */
  855. void EmplaceValue()
  856. {
  857. this->GetState()->EmplaceResult(0);
  858. }
  859. private:
  860. /** Whether a future has already been retrieved from this promise. */
  861. bool FutureRetrieved;
  862. };
  863. /* TWwiseFuture::Then
  864. *****************************************************************************/
  865. namespace FutureDetail
  866. {
  867. /**
  868. * Template for setting a promise value from a continuation.
  869. */
  870. template<typename Func, typename ParamType, typename ResultType>
  871. inline void SetPromiseValue(TWwisePromise<ResultType>& Promise, Func& Function, TWwiseFuture<ParamType>&& Param)
  872. {
  873. Promise.SetValue(Function(MoveTemp(Param)));
  874. }
  875. template<typename Func, typename ParamType>
  876. inline void SetPromiseValue(TWwisePromise<void>& Promise, Func& Function, TWwiseFuture<ParamType>&& Param)
  877. {
  878. Function(MoveTemp(Param));
  879. Promise.SetValue();
  880. }
  881. }
  882. // Then implementation
  883. template<typename InternalResultType>
  884. template<typename Func>
  885. auto TWwiseFutureBase<InternalResultType>::Then(Func Continuation) //-> TWwiseFuture<decltype(Continuation(MoveTemp(TWwiseFuture<InternalResultType>())))>
  886. {
  887. check(IsValid());
  888. using ReturnValue = decltype(Continuation(MoveTemp(TWwiseFuture<InternalResultType>())));
  889. TWwisePromise<ReturnValue> Promise;
  890. TWwiseFuture<ReturnValue> FutureResult = Promise.GetFuture();
  891. TUniqueFunction<void()> Callback = [PromiseCapture = MoveTemp(Promise), ContinuationCapture = MoveTemp(Continuation), StateCapture = this->State]() mutable
  892. {
  893. FutureDetail::SetPromiseValue(PromiseCapture, ContinuationCapture, TWwiseFuture<InternalResultType>(MoveTemp(StateCapture)));
  894. };
  895. // This invalidate this future.
  896. StateType MovedState = MoveTemp(this->State);
  897. MovedState->SetContinuation(MoveTemp(Callback));
  898. return FutureResult;
  899. }
  900. // Next implementation
  901. template<typename InternalResultType>
  902. template<typename Func>
  903. auto TWwiseFutureBase<InternalResultType>::Next(Func Continuation) //-> TWwiseFuture<decltype(Continuation(Get()))>
  904. {
  905. return this->Then([Continuation = MoveTemp(Continuation)](TWwiseFuture<InternalResultType> Self) mutable
  906. {
  907. return Continuation(Self.Get());
  908. });
  909. }
  910. /** Helper to create and immediately fulfill a promise */
  911. template<typename ResultType, typename... ArgTypes>
  912. TWwisePromise<ResultType> MakeFulfilledWwisePromise(ArgTypes&&... Args)
  913. {
  914. TWwisePromise<ResultType> Promise;
  915. Promise.EmplaceValue(Forward<ArgTypes>(Args)...);
  916. return Promise;
  917. }