WwiseFuture.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  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 "HAL/PlatformProcess.h"
  25. #include "Misc/ScopeLock.h"
  26. #include "Wwise/Stats/Concurrency.h"
  27. #include "Wwise/Stats/AsyncStats.h"
  28. //
  29. // WwiseFuture is a replica of Unreal's Async/Future.h code, with optimizations on the FutureState to reduce the
  30. // amount of FCriticalSection and FEvent to the bare minimum. Most of Wwise Integrations code uses the "Then" paradigm
  31. // of Futures/Promises instead of the Wait paradigm. Even when waiting a result, it is usually ready for usage.
  32. //
  33. // This means there is a very strong chance a Future doesn't need to retrieve an Event from its pool of resources.
  34. //
  35. // Since some platforms have set amount of hardware synchronization primitites, it's preferable to reduce the number of
  36. // them to a minimum. Although they are useful for actually waiting for a longer operation to finish in a particular
  37. // thread, even then, there will usually be one lengthy operation, and all the subsequent operations will be done
  38. // instantaneously without a lock.
  39. //
  40. /**
  41. * Base class for the internal state of asynchronous return values (futures).
  42. */
  43. class FWwiseFutureState
  44. {
  45. public:
  46. /** Default constructor. */
  47. FWwiseFutureState()
  48. : CompletionCallback(nullptr)
  49. , CompletionEvent(nullptr)
  50. , Complete(false)
  51. {
  52. ASYNC_INC_DWORD_STAT(STAT_WwiseFutures);
  53. }
  54. /**
  55. * Create and initialize a new instance with a callback.
  56. *
  57. * @param InCompletionCallback A function that is called when the state is completed.
  58. */
  59. FWwiseFutureState(TUniqueFunction<void()>&& InCompletionCallback)
  60. : CompletionCallback(InCompletionCallback ? new TUniqueFunction<void()>(MoveTemp(InCompletionCallback)) : nullptr)
  61. , CompletionEvent(nullptr)
  62. , Complete(false)
  63. {
  64. ASYNC_INC_DWORD_STAT(STAT_WwiseFutures);
  65. }
  66. /** Destructor. */
  67. ~FWwiseFutureState()
  68. {
  69. ASYNC_DEC_DWORD_STAT(STAT_WwiseFutures);
  70. if (CompletionCallback)
  71. {
  72. delete CompletionCallback;
  73. CompletionCallback = nullptr;
  74. }
  75. if (CompletionEvent)
  76. {
  77. FPlatformProcess::ReturnSynchEventToPool(CompletionEvent);
  78. CompletionEvent = nullptr;
  79. ASYNC_DEC_DWORD_STAT(STAT_WwiseFuturesWithEvent);
  80. }
  81. }
  82. public:
  83. /**
  84. * Checks whether the asynchronous result has been set.
  85. *
  86. * @return true if the result has been set, false otherwise.
  87. * @see WaitFor
  88. */
  89. bool IsComplete() const
  90. {
  91. return Complete.Load(EMemoryOrder::SequentiallyConsistent);
  92. }
  93. /**
  94. * Blocks the calling thread until the future result is available.
  95. *
  96. * @param Duration The maximum time span to wait for the future result.
  97. * @return true if the result is available, false otherwise.
  98. * @see IsComplete
  99. */
  100. bool WaitFor(const FTimespan& Duration) const
  101. {
  102. if (IsComplete())
  103. {
  104. return true;
  105. }
  106. SCOPED_WWISECONCURRENCY_EVENT_4(TEXT("FWwiseFutureState::WaitFor"));
  107. FEvent* CompletionEventToUse = CompletionEvent.Load(EMemoryOrder::SequentiallyConsistent);
  108. if (!CompletionEventToUse)
  109. {
  110. auto* NewCompletionEvent = FPlatformProcess::GetSynchEventFromPool(true);
  111. if (CompletionEvent.CompareExchange(CompletionEventToUse, NewCompletionEvent))
  112. {
  113. CompletionEventToUse = NewCompletionEvent;
  114. ASYNC_INC_DWORD_STAT(STAT_WwiseFuturesWithEvent);
  115. }
  116. else
  117. {
  118. FPlatformProcess::ReturnSynchEventToPool(NewCompletionEvent);
  119. }
  120. if (IsComplete())
  121. {
  122. return true;
  123. }
  124. }
  125. const bool bIsInGameThread = IsInGameThread();
  126. CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyGameThreadWait, bIsInGameThread);
  127. CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_WwiseConcurrencyWait, !bIsInGameThread);
  128. if (CompletionEventToUse->Wait(Duration))
  129. {
  130. return true;
  131. }
  132. return false;
  133. }
  134. /**
  135. * Set a continuation to be called on completion of the promise
  136. * @param Continuation
  137. */
  138. void SetContinuation(TUniqueFunction<void()>&& Continuation)
  139. {
  140. if (IsComplete())
  141. {
  142. if (Continuation)
  143. {
  144. Continuation();
  145. }
  146. return;
  147. }
  148. // Store the Copy to the CompletionCallback
  149. auto Copy = Continuation ? new TUniqueFunction<void()>(MoveTemp(Continuation)) : nullptr;
  150. auto OldCopy = CompletionCallback.Exchange(Copy);
  151. check(!OldCopy); // We can only execute one continuation per WwiseFuture.
  152. if (!IsComplete())
  153. {
  154. return;
  155. }
  156. // We are already complete. See if we need to execute ourselves.
  157. Copy = CompletionCallback.Exchange(nullptr);
  158. if (Copy)
  159. {
  160. (*Copy)();
  161. delete Copy;
  162. }
  163. }
  164. protected:
  165. /** Notifies any waiting threads that the result is available. */
  166. void MarkComplete()
  167. {
  168. Complete.Store(true, EMemoryOrder::SequentiallyConsistent);
  169. FEvent* Event = CompletionEvent.Load(EMemoryOrder::SequentiallyConsistent);
  170. auto* Continuation = CompletionCallback.Exchange(nullptr);
  171. if (Event)
  172. {
  173. Event->Trigger();
  174. }
  175. if (Continuation)
  176. {
  177. (*Continuation)();
  178. delete Continuation;
  179. }
  180. }
  181. private:
  182. /** An optional callback function that is executed the state is completed. */
  183. TAtomic< TUniqueFunction<void()>* > CompletionCallback;
  184. /** Holds an event signaling that the result is available. */
  185. mutable TAtomic< FEvent* > CompletionEvent;
  186. /** Whether the asynchronous result is available. */
  187. TAtomic<bool> Complete;
  188. };
  189. /**
  190. * Implements the internal state of asynchronous return values (futures).
  191. */
  192. template<typename InternalResultType>
  193. class TWwiseFutureState
  194. : public FWwiseFutureState
  195. {
  196. public:
  197. /** Default constructor. */
  198. TWwiseFutureState()
  199. : FWwiseFutureState()
  200. { }
  201. ~TWwiseFutureState()
  202. {
  203. if (IsComplete())
  204. {
  205. DestructItem(Result.GetTypedPtr());
  206. }
  207. }
  208. /**
  209. * Create and initialize a new instance with a callback.
  210. *
  211. * @param CompletionCallback A function that is called when the state is completed.
  212. */
  213. TWwiseFutureState(TUniqueFunction<void()>&& CompletionCallback)
  214. : FWwiseFutureState(MoveTemp(CompletionCallback))
  215. { }
  216. public:
  217. /**
  218. * Gets the result (will block the calling thread until the result is available).
  219. *
  220. * @return The result value.
  221. * @see EmplaceResult
  222. */
  223. const InternalResultType& GetResult() const
  224. {
  225. while (!IsComplete())
  226. {
  227. WaitFor(FTimespan::MaxValue());
  228. }
  229. return *Result.GetTypedPtr();
  230. }
  231. /**
  232. * Sets the result and notifies any waiting threads.
  233. *
  234. * @param InResult The result to set.
  235. * @see GetResult
  236. */
  237. template<typename... ArgTypes>
  238. void EmplaceResult(ArgTypes&&... Args)
  239. {
  240. check(!IsComplete());
  241. new(Result.GetTypedPtr()) InternalResultType(Forward<ArgTypes>(Args)...);
  242. MarkComplete();
  243. }
  244. private:
  245. /** Holds the asynchronous result. */
  246. TTypeCompatibleBytes<InternalResultType> Result;
  247. };
  248. /* TWwiseFuture
  249. *****************************************************************************/
  250. /**
  251. * Abstract base template for futures and shared futures.
  252. */
  253. template<typename InternalResultType>
  254. class TWwiseFutureBase
  255. {
  256. public:
  257. /**
  258. * Checks whether this future object has its value set.
  259. *
  260. * @return true if this future has a shared state and the value has been set, false otherwise.
  261. * @see IsValid
  262. */
  263. bool IsReady() const
  264. {
  265. return State.IsValid() ? State->IsComplete() : false;
  266. }
  267. /**
  268. * Checks whether this future object has a valid state.
  269. *
  270. * @return true if the state is valid, false otherwise.
  271. * @see IsReady
  272. */
  273. bool IsValid() const
  274. {
  275. return State.IsValid();
  276. }
  277. /**
  278. * Blocks the calling thread until the future result is available.
  279. *
  280. * Note that this method may block forever if the result is never set. Use
  281. * the WaitFor or WaitUntil methods to specify a maximum timeout for the wait.
  282. *
  283. * @see WaitFor, WaitUntil
  284. */
  285. void Wait() const
  286. {
  287. if (State.IsValid())
  288. {
  289. while (!WaitFor(FTimespan::MaxValue()));
  290. }
  291. }
  292. /**
  293. * Blocks the calling thread until the future result is available or the specified duration is exceeded.
  294. *
  295. * @param Duration The maximum time span to wait for the future result.
  296. * @return true if the result is available, false otherwise.
  297. * @see Wait, WaitUntil
  298. */
  299. bool WaitFor(const FTimespan& Duration) const
  300. {
  301. return State.IsValid() ? State->WaitFor(Duration) : false;
  302. }
  303. /**
  304. * Blocks the calling thread until the future result is available or the specified time is hit.
  305. *
  306. * @param Time The time until to wait for the future result (in UTC).
  307. * @return true if the result is available, false otherwise.
  308. * @see Wait, WaitUntil
  309. */
  310. bool WaitUntil(const FDateTime& Time) const
  311. {
  312. return WaitFor(Time - FDateTime::UtcNow());
  313. }
  314. protected:
  315. typedef TSharedPtr<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe> StateType;
  316. /** Default constructor. */
  317. TWwiseFutureBase() { }
  318. /**
  319. * Creates and initializes a new instance.
  320. *
  321. * @param InState The shared state to initialize with.
  322. */
  323. TWwiseFutureBase(const StateType& InState)
  324. : State(InState)
  325. { }
  326. /**
  327. * Protected move construction
  328. */
  329. TWwiseFutureBase(TWwiseFutureBase&&) = default;
  330. /**
  331. * Protected move assignment
  332. */
  333. TWwiseFutureBase& operator=(TWwiseFutureBase&&) = default;
  334. /**
  335. * Protected copy construction
  336. */
  337. TWwiseFutureBase(const TWwiseFutureBase&) = default;
  338. /**
  339. * Protected copy assignment
  340. */
  341. TWwiseFutureBase& operator=(const TWwiseFutureBase&) = default;
  342. /** Protected destructor. */
  343. ~TWwiseFutureBase() { }
  344. protected:
  345. /**
  346. * Gets the shared state object.
  347. *
  348. * @return The shared state object.
  349. */
  350. const StateType& GetState() const
  351. {
  352. // if you hit this assertion then your future has an invalid state.
  353. // this happens if you have an uninitialized future or if you moved
  354. // it to another instance.
  355. check(State.IsValid());
  356. return State;
  357. }
  358. /**
  359. * Set a completion callback that will be called once the future completes
  360. * or immediately if already completed
  361. *
  362. * @param Continuation a continuation taking an argument of type TWwiseFuture<InternalResultType>
  363. * @return nothing at the moment but could return another future to allow future chaining
  364. */
  365. template<typename Func>
  366. auto Then(Func Continuation);
  367. /**
  368. * Convenience wrapper for Then that
  369. * set a completion callback that will be called once the future completes
  370. * or immediately if already completed
  371. * @param Continuation a continuation taking an argument of type InternalResultType
  372. * @return nothing at the moment but could return another future to allow future chaining
  373. */
  374. template<typename Func>
  375. auto Next(Func Continuation);
  376. /**
  377. * Reset the future.
  378. * Reseting a future removes any continuation from its shared state and invalidates it.
  379. * Useful for discarding yet to be completed future cleanly.
  380. */
  381. void Reset()
  382. {
  383. if (IsValid())
  384. {
  385. this->State->SetContinuation(nullptr);
  386. this->State.Reset();
  387. }
  388. }
  389. private:
  390. /** Holds the future's state. */
  391. StateType State;
  392. };
  393. template<typename ResultType> class TWwiseSharedFuture;
  394. /**
  395. * Template for unshared futures.
  396. */
  397. template<typename ResultType>
  398. class TWwiseFuture
  399. : public TWwiseFutureBase<ResultType>
  400. {
  401. typedef TWwiseFutureBase<ResultType> BaseType;
  402. public:
  403. /** Default constructor. */
  404. TWwiseFuture() { }
  405. /**
  406. * Creates and initializes a new instance.
  407. *
  408. * @param InState The shared state to initialize with.
  409. */
  410. TWwiseFuture(const typename BaseType::StateType& InState)
  411. : BaseType(InState)
  412. { }
  413. /**
  414. * Move constructor.
  415. */
  416. TWwiseFuture(TWwiseFuture&&) = default;
  417. /**
  418. * Move assignment operator.
  419. */
  420. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  421. /** Destructor. */
  422. ~TWwiseFuture() { }
  423. public:
  424. /**
  425. * Gets the future's result.
  426. *
  427. * @return The result.
  428. */
  429. ResultType Get() const
  430. {
  431. return this->GetState()->GetResult();
  432. }
  433. /**
  434. * Moves this future's state into a shared future.
  435. *
  436. * @return The shared future object.
  437. */
  438. TWwiseSharedFuture<ResultType> Share()
  439. {
  440. return TWwiseSharedFuture<ResultType>(MoveTemp(*this));
  441. }
  442. /**
  443. * Expose Then functionality
  444. * @see TWwiseFutureBase
  445. */
  446. using BaseType::Then;
  447. /**
  448. * Expose Next functionality
  449. * @see TWwiseFutureBase
  450. */
  451. using BaseType::Next;
  452. /**
  453. * Expose Reset functionality
  454. * @see TWwiseFutureBase
  455. */
  456. using BaseType::Reset;
  457. private:
  458. /** Hidden copy constructor (futures cannot be copied). */
  459. TWwiseFuture(const TWwiseFuture&);
  460. /** Hidden copy assignment (futures cannot be copied). */
  461. TWwiseFuture& operator=(const TWwiseFuture&);
  462. };
  463. /**
  464. * Template for unshared futures (specialization for reference types).
  465. */
  466. template<typename ResultType>
  467. class TWwiseFuture<ResultType&>
  468. : public TWwiseFutureBase<ResultType*>
  469. {
  470. typedef TWwiseFutureBase<ResultType*> BaseType;
  471. public:
  472. /** Default constructor. */
  473. TWwiseFuture() { }
  474. /**
  475. * Creates and initializes a new instance.
  476. *
  477. * @param InState The shared state to initialize with.
  478. */
  479. TWwiseFuture(const typename BaseType::StateType& InState)
  480. : BaseType(InState)
  481. { }
  482. /**
  483. * Move constructor.
  484. */
  485. TWwiseFuture(TWwiseFuture&&) = default;
  486. /**
  487. * Move assignment operator.
  488. */
  489. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  490. /** Destructor. */
  491. ~TWwiseFuture() { }
  492. public:
  493. /**
  494. * Gets the future's result.
  495. *
  496. * @return The result.
  497. */
  498. ResultType& Get() const
  499. {
  500. return *this->GetState()->GetResult();
  501. }
  502. /**
  503. * Moves this future's state into a shared future.
  504. *
  505. * @return The shared future object.
  506. */
  507. TWwiseSharedFuture<ResultType&> Share()
  508. {
  509. return TWwiseSharedFuture<ResultType&>(MoveTemp(*this));
  510. }
  511. /**
  512. * Expose Then functionality
  513. * @see TWwiseFutureBase
  514. */
  515. using BaseType::Then;
  516. /**
  517. * Expose Next functionality
  518. * @see TWwiseFutureBase
  519. */
  520. using BaseType::Next;
  521. /**
  522. * Expose Reset functionality
  523. * @see TWwiseFutureBase
  524. */
  525. using BaseType::Reset;
  526. private:
  527. /** Hidden copy constructor (futures cannot be copied). */
  528. TWwiseFuture(const TWwiseFuture&);
  529. /** Hidden copy assignment (futures cannot be copied). */
  530. TWwiseFuture& operator=(const TWwiseFuture&);
  531. };
  532. /**
  533. * Template for unshared futures (specialization for void).
  534. */
  535. template<>
  536. class TWwiseFuture<void>
  537. : public TWwiseFutureBase<int>
  538. {
  539. typedef TWwiseFutureBase<int> BaseType;
  540. public:
  541. /** Default constructor. */
  542. TWwiseFuture() { }
  543. /**
  544. * Creates and initializes a new instance.
  545. *
  546. * @param InState The shared state to initialize with.
  547. */
  548. TWwiseFuture(const BaseType::StateType& InState)
  549. : BaseType(InState)
  550. { }
  551. /**
  552. * Move constructor.
  553. */
  554. TWwiseFuture(TWwiseFuture&&) = default;
  555. /**
  556. * Move assignment operator.
  557. */
  558. TWwiseFuture& operator=(TWwiseFuture&& Other) = default;
  559. /** Destructor. */
  560. ~TWwiseFuture() { }
  561. public:
  562. /**
  563. * Gets the future's result.
  564. *
  565. * @return The result.
  566. */
  567. void Get() const
  568. {
  569. GetState()->GetResult();
  570. }
  571. /**
  572. * Moves this future's state into a shared future.
  573. *
  574. * @return The shared future object.
  575. */
  576. TWwiseSharedFuture<void> Share();
  577. /**
  578. * Expose Then functionality
  579. * @see TWwiseFutureBase
  580. */
  581. using BaseType::Then;
  582. /**
  583. * Expose Next functionality
  584. * @see TWwiseFutureBase
  585. */
  586. using BaseType::Next;
  587. /**
  588. * Expose Reset functionality
  589. * @see TWwiseFutureBase
  590. */
  591. using BaseType::Reset;
  592. private:
  593. /** Hidden copy constructor (futures cannot be copied). */
  594. TWwiseFuture(const TWwiseFuture&);
  595. /** Hidden copy assignment (futures cannot be copied). */
  596. TWwiseFuture& operator=(const TWwiseFuture&);
  597. };
  598. /* TWwiseSharedFuture
  599. *****************************************************************************/
  600. /**
  601. * Template for shared futures.
  602. */
  603. template<typename ResultType>
  604. class TWwiseSharedFuture
  605. : public TWwiseFutureBase<ResultType>
  606. {
  607. typedef TWwiseFutureBase<ResultType> BaseType;
  608. public:
  609. /** Default constructor. */
  610. TWwiseSharedFuture() { }
  611. /**
  612. * Creates and initializes a new instance.
  613. *
  614. * @param InState The shared state to initialize from.
  615. */
  616. TWwiseSharedFuture(const typename BaseType::StateType& InState)
  617. : BaseType(InState)
  618. { }
  619. /**
  620. * Creates and initializes a new instances from a future object.
  621. *
  622. * @param Future The future object to initialize from.
  623. */
  624. TWwiseSharedFuture(TWwiseFuture<ResultType>&& Future)
  625. : BaseType(MoveTemp(Future))
  626. { }
  627. /**
  628. * Copy constructor.
  629. */
  630. TWwiseSharedFuture(const TWwiseSharedFuture&) = default;
  631. /**
  632. * Copy assignment operator.
  633. */
  634. TWwiseSharedFuture& operator=(const TWwiseSharedFuture& Other) = default;
  635. /**
  636. * Move constructor.
  637. */
  638. TWwiseSharedFuture(TWwiseSharedFuture&&) = default;
  639. /**
  640. * Move assignment operator.
  641. */
  642. TWwiseSharedFuture& operator=(TWwiseSharedFuture&& Other) = default;
  643. /** Destructor. */
  644. ~TWwiseSharedFuture() { }
  645. public:
  646. /**
  647. * Gets the future's result.
  648. *
  649. * @return The result.
  650. */
  651. ResultType Get() const
  652. {
  653. return this->GetState()->GetResult();
  654. }
  655. };
  656. /**
  657. * Template for shared futures (specialization for reference types).
  658. */
  659. template<typename ResultType>
  660. class TWwiseSharedFuture<ResultType&>
  661. : public TWwiseFutureBase<ResultType*>
  662. {
  663. typedef TWwiseFutureBase<ResultType*> BaseType;
  664. public:
  665. /** Default constructor. */
  666. TWwiseSharedFuture() { }
  667. /**
  668. * Creates and initializes a new instance.
  669. *
  670. * @param InState The shared state to initialize from.
  671. */
  672. TWwiseSharedFuture(const typename BaseType::StateType& InState)
  673. : BaseType(InState)
  674. { }
  675. /**
  676. * Creates and initializes a new instances from a future object.
  677. *
  678. * @param Future The future object to initialize from.
  679. */
  680. TWwiseSharedFuture(TWwiseFuture<ResultType>&& Future)
  681. : BaseType(MoveTemp(Future))
  682. { }
  683. /**
  684. * Copy constructor.
  685. */
  686. TWwiseSharedFuture(const TWwiseSharedFuture&) = default;
  687. /** Copy assignment operator. */
  688. TWwiseSharedFuture& operator=(const TWwiseSharedFuture& Other) = default;
  689. /**
  690. * Move constructor.
  691. */
  692. TWwiseSharedFuture(TWwiseSharedFuture&&) = default;
  693. /**
  694. * Move assignment operator.
  695. */
  696. TWwiseSharedFuture& operator=(TWwiseSharedFuture&& Other) = default;
  697. /** Destructor. */
  698. ~TWwiseSharedFuture() { }
  699. public:
  700. /**
  701. * Gets the future's result.
  702. *
  703. * @return The result.
  704. */
  705. ResultType& Get() const
  706. {
  707. return *this->GetState()->GetResult();
  708. }
  709. };
  710. /**
  711. * Template for shared futures (specialization for void).
  712. */
  713. template<>
  714. class TWwiseSharedFuture<void>
  715. : public TWwiseFutureBase<int>
  716. {
  717. typedef TWwiseFutureBase<int> BaseType;
  718. public:
  719. /** Default constructor. */
  720. TWwiseSharedFuture() { }
  721. /**
  722. * Creates and initializes a new instance from shared state.
  723. *
  724. * @param InState The shared state to initialize from.
  725. */
  726. TWwiseSharedFuture(const BaseType::StateType& InState)
  727. : BaseType(InState)
  728. { }
  729. /**
  730. * Creates and initializes a new instances from a future object.
  731. *
  732. * @param Future The future object to initialize from.
  733. */
  734. TWwiseSharedFuture(TWwiseFuture<void>&& Future)
  735. : BaseType(MoveTemp(Future))
  736. { }
  737. /**
  738. * Copy constructor.
  739. */
  740. TWwiseSharedFuture(const TWwiseSharedFuture&) = default;
  741. /**
  742. * Copy assignment operator.
  743. */
  744. TWwiseSharedFuture& operator=(const TWwiseSharedFuture& Other) = default;
  745. /**
  746. * Move constructor.
  747. */
  748. TWwiseSharedFuture(TWwiseSharedFuture&&) = default;
  749. /**
  750. * Move assignment operator.
  751. */
  752. TWwiseSharedFuture& operator=(TWwiseSharedFuture&& Other) = default;
  753. /** Destructor. */
  754. ~TWwiseSharedFuture() { }
  755. public:
  756. /**
  757. * Gets the future's result.
  758. *
  759. * @return The result.
  760. */
  761. void Get() const
  762. {
  763. GetState()->GetResult();
  764. }
  765. };
  766. inline TWwiseSharedFuture<void> TWwiseFuture<void>::Share()
  767. {
  768. return TWwiseSharedFuture<void>(MoveTemp(*this));
  769. }
  770. /* TWwisePromise
  771. *****************************************************************************/
  772. template<typename InternalResultType>
  773. class TWwisePromiseBase
  774. : FNoncopyable
  775. {
  776. typedef TSharedPtr<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe> StateType;
  777. public:
  778. /** Default constructor. */
  779. TWwisePromiseBase()
  780. : State(MakeShared<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe>())
  781. { }
  782. /**
  783. * Move constructor.
  784. *
  785. * @param Other The promise holding the shared state to move.
  786. */
  787. TWwisePromiseBase(TWwisePromiseBase&& Other)
  788. : State(MoveTemp(Other.State))
  789. {
  790. Other.State.Reset();
  791. }
  792. /**
  793. * Create and initialize a new instance with a callback.
  794. *
  795. * @param CompletionCallback A function that is called when the future state is completed.
  796. */
  797. TWwisePromiseBase(TUniqueFunction<void()>&& CompletionCallback)
  798. : State(MakeShared<TWwiseFutureState<InternalResultType>, ESPMode::ThreadSafe>(MoveTemp(CompletionCallback)))
  799. { }
  800. public:
  801. /** Move assignment operator. */
  802. TWwisePromiseBase& operator=(TWwisePromiseBase&& Other)
  803. {
  804. State = Other.State;
  805. Other.State.Reset();
  806. return *this;
  807. }
  808. protected:
  809. /** Destructor. */
  810. ~TWwisePromiseBase()
  811. {
  812. if (State.IsValid())
  813. {
  814. // if you hit this assertion then your promise never had its result
  815. // value set. broken promises are considered programming errors.
  816. check(State->IsComplete());
  817. State.Reset();
  818. }
  819. }
  820. /**
  821. * Gets the shared state object.
  822. *
  823. * @return The shared state object.
  824. */
  825. const StateType& GetState()
  826. {
  827. // if you hit this assertion then your promise has an invalid state.
  828. // this happens if you move the promise to another instance.
  829. check(State.IsValid());
  830. return State;
  831. }
  832. private:
  833. /** Holds the shared state object. */
  834. StateType State;
  835. };
  836. /**
  837. * Template for promises.
  838. */
  839. template<typename ResultType>
  840. class TWwisePromise
  841. : public TWwisePromiseBase<ResultType>
  842. {
  843. public:
  844. typedef TWwisePromiseBase<ResultType> BaseType;
  845. /** Default constructor (creates a new shared state). */
  846. TWwisePromise()
  847. : BaseType()
  848. , FutureRetrieved(false)
  849. { }
  850. /**
  851. * Move constructor.
  852. *
  853. * @param Other The promise holding the shared state to move.
  854. */
  855. TWwisePromise(TWwisePromise&& Other)
  856. : BaseType(MoveTemp(Other))
  857. , FutureRetrieved(MoveTemp(Other.FutureRetrieved))
  858. { }
  859. /**
  860. * Create and initialize a new instance with a callback.
  861. *
  862. * @param CompletionCallback A function that is called when the future state is completed.
  863. */
  864. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  865. : BaseType(MoveTemp(CompletionCallback))
  866. , FutureRetrieved(false)
  867. { }
  868. public:
  869. /**
  870. * Move assignment operator.
  871. *
  872. * @param Other The promise holding the shared state to move.
  873. */
  874. TWwisePromise& operator=(TWwisePromise&& Other)
  875. {
  876. BaseType::operator=(MoveTemp(Other));
  877. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  878. return *this;
  879. }
  880. public:
  881. /**
  882. * Gets a TWwiseFuture object associated with the shared state of this promise.
  883. *
  884. * @return The TWwiseFuture object.
  885. */
  886. TWwiseFuture<ResultType> GetFuture()
  887. {
  888. check(!FutureRetrieved);
  889. FutureRetrieved = true;
  890. return TWwiseFuture<ResultType>(this->GetState());
  891. }
  892. /**
  893. * Sets the promised result.
  894. *
  895. * The result must be set only once. An assertion will
  896. * be triggered if this method is called a second time.
  897. *
  898. * @param Result The result value to set.
  899. */
  900. FORCEINLINE void SetValue(const ResultType& Result)
  901. {
  902. EmplaceValue(Result);
  903. }
  904. /**
  905. * Sets the promised result (from rvalue).
  906. *
  907. * The result must be set only once. An assertion will
  908. * be triggered if this method is called a second time.
  909. *
  910. * @param Result The result value to set.
  911. */
  912. FORCEINLINE void SetValue(ResultType&& Result)
  913. {
  914. EmplaceValue(MoveTemp(Result));
  915. }
  916. /**
  917. * Sets the promised result.
  918. *
  919. * The result must be set only once. An assertion will
  920. * be triggered if this method is called a second time.
  921. *
  922. * @param Result The result value to set.
  923. */
  924. template<typename... ArgTypes>
  925. void EmplaceValue(ArgTypes&&... Args)
  926. {
  927. this->GetState()->EmplaceResult(Forward<ArgTypes>(Args)...);
  928. }
  929. private:
  930. /** Whether a future has already been retrieved from this promise. */
  931. bool FutureRetrieved;
  932. };
  933. /**
  934. * Template for promises (specialization for reference types).
  935. */
  936. template<typename ResultType>
  937. class TWwisePromise<ResultType&>
  938. : public TWwisePromiseBase<ResultType*>
  939. {
  940. typedef TWwisePromiseBase<ResultType*> BaseType;
  941. public:
  942. /** Default constructor (creates a new shared state). */
  943. TWwisePromise()
  944. : BaseType()
  945. , FutureRetrieved(false)
  946. { }
  947. /**
  948. * Move constructor.
  949. *
  950. * @param Other The promise holding the shared state to move.
  951. */
  952. TWwisePromise(TWwisePromise&& Other)
  953. : BaseType(MoveTemp(Other))
  954. , FutureRetrieved(MoveTemp(Other.FutureRetrieved))
  955. { }
  956. /**
  957. * Create and initialize a new instance with a callback.
  958. *
  959. * @param CompletionCallback A function that is called when the future state is completed.
  960. */
  961. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  962. : BaseType(MoveTemp(CompletionCallback))
  963. , FutureRetrieved(false)
  964. { }
  965. public:
  966. /**
  967. * Move assignment operator.
  968. *
  969. * @param Other The promise holding the shared state to move.
  970. */
  971. TWwisePromise& operator=(TWwisePromise&& Other)
  972. {
  973. BaseType::operator=(MoveTemp(Other));
  974. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  975. return this;
  976. }
  977. public:
  978. /**
  979. * Gets a TWwiseFuture object associated with the shared state of this promise.
  980. *
  981. * @return The TWwiseFuture object.
  982. */
  983. TWwiseFuture<ResultType&> GetFuture()
  984. {
  985. check(!FutureRetrieved);
  986. FutureRetrieved = true;
  987. return TWwiseFuture<ResultType&>(this->GetState());
  988. }
  989. /**
  990. * Sets the promised result.
  991. *
  992. * The result must be set only once. An assertion will
  993. * be triggered if this method is called a second time.
  994. *
  995. * @param Result The result value to set.
  996. */
  997. FORCEINLINE void SetValue(ResultType& Result)
  998. {
  999. EmplaceValue(Result);
  1000. }
  1001. /**
  1002. * Sets the promised result.
  1003. *
  1004. * The result must be set only once. An assertion will
  1005. * be triggered if this method is called a second time.
  1006. *
  1007. * @param Result The result value to set.
  1008. */
  1009. void EmplaceValue(ResultType& Result)
  1010. {
  1011. this->GetState()->EmplaceResult(&Result);
  1012. }
  1013. private:
  1014. /** Whether a future has already been retrieved from this promise. */
  1015. bool FutureRetrieved;
  1016. };
  1017. /**
  1018. * Template for promises (specialization for void results).
  1019. */
  1020. template<>
  1021. class TWwisePromise<void>
  1022. : public TWwisePromiseBase<int>
  1023. {
  1024. typedef TWwisePromiseBase<int> BaseType;
  1025. public:
  1026. /** Default constructor (creates a new shared state). */
  1027. TWwisePromise()
  1028. : BaseType()
  1029. , FutureRetrieved(false)
  1030. { }
  1031. /**
  1032. * Move constructor.
  1033. *
  1034. * @param Other The promise holding the shared state to move.
  1035. */
  1036. TWwisePromise(TWwisePromise&& Other)
  1037. : BaseType(MoveTemp(Other))
  1038. , FutureRetrieved(false)
  1039. { }
  1040. /**
  1041. * Create and initialize a new instance with a callback.
  1042. *
  1043. * @param CompletionCallback A function that is called when the future state is completed.
  1044. */
  1045. TWwisePromise(TUniqueFunction<void()>&& CompletionCallback)
  1046. : BaseType(MoveTemp(CompletionCallback))
  1047. , FutureRetrieved(false)
  1048. { }
  1049. public:
  1050. /**
  1051. * Move assignment operator.
  1052. *
  1053. * @param Other The promise holding the shared state to move.
  1054. */
  1055. TWwisePromise& operator=(TWwisePromise&& Other)
  1056. {
  1057. BaseType::operator=(MoveTemp(Other));
  1058. FutureRetrieved = MoveTemp(Other.FutureRetrieved);
  1059. return *this;
  1060. }
  1061. public:
  1062. /**
  1063. * Gets a TWwiseFuture object associated with the shared state of this promise.
  1064. *
  1065. * @return The TWwiseFuture object.
  1066. */
  1067. TWwiseFuture<void> GetFuture()
  1068. {
  1069. check(!FutureRetrieved);
  1070. FutureRetrieved = true;
  1071. return TWwiseFuture<void>(GetState());
  1072. }
  1073. /**
  1074. * Sets the promised result.
  1075. *
  1076. * The result must be set only once. An assertion will
  1077. * be triggered if this method is called a second time.
  1078. */
  1079. FORCEINLINE void SetValue()
  1080. {
  1081. EmplaceValue();
  1082. }
  1083. /**
  1084. * Sets the promised result.
  1085. *
  1086. * The result must be set only once. An assertion will
  1087. * be triggered if this method is called a second time.
  1088. *
  1089. * @param Result The result value to set.
  1090. */
  1091. void EmplaceValue()
  1092. {
  1093. this->GetState()->EmplaceResult(0);
  1094. }
  1095. private:
  1096. /** Whether a future has already been retrieved from this promise. */
  1097. bool FutureRetrieved;
  1098. };
  1099. /* TWwiseFuture::Then
  1100. *****************************************************************************/
  1101. namespace FutureDetail
  1102. {
  1103. /**
  1104. * Template for setting a promise value from a continuation.
  1105. */
  1106. template<typename Func, typename ParamType, typename ResultType>
  1107. inline void SetPromiseValue(TWwisePromise<ResultType>& Promise, Func& Function, TWwiseFuture<ParamType>&& Param)
  1108. {
  1109. Promise.SetValue(Function(MoveTemp(Param)));
  1110. }
  1111. template<typename Func, typename ParamType>
  1112. inline void SetPromiseValue(TWwisePromise<void>& Promise, Func& Function, TWwiseFuture<ParamType>&& Param)
  1113. {
  1114. Function(MoveTemp(Param));
  1115. Promise.SetValue();
  1116. }
  1117. }
  1118. // Then implementation
  1119. template<typename InternalResultType>
  1120. template<typename Func>
  1121. auto TWwiseFutureBase<InternalResultType>::Then(Func Continuation) //-> TWwiseFuture<decltype(Continuation(MoveTemp(TWwiseFuture<InternalResultType>())))>
  1122. {
  1123. check(IsValid());
  1124. using ReturnValue = decltype(Continuation(MoveTemp(TWwiseFuture<InternalResultType>())));
  1125. TWwisePromise<ReturnValue> Promise;
  1126. TWwiseFuture<ReturnValue> FutureResult = Promise.GetFuture();
  1127. TUniqueFunction<void()> Callback = [PromiseCapture = MoveTemp(Promise), ContinuationCapture = MoveTemp(Continuation), StateCapture = this->State]() mutable
  1128. {
  1129. FutureDetail::SetPromiseValue(PromiseCapture, ContinuationCapture, TWwiseFuture<InternalResultType>(MoveTemp(StateCapture)));
  1130. };
  1131. // This invalidate this future.
  1132. StateType MovedState = MoveTemp(this->State);
  1133. MovedState->SetContinuation(MoveTemp(Callback));
  1134. return FutureResult;
  1135. }
  1136. // Next implementation
  1137. template<typename InternalResultType>
  1138. template<typename Func>
  1139. auto TWwiseFutureBase<InternalResultType>::Next(Func Continuation) //-> TWwiseFuture<decltype(Continuation(Get()))>
  1140. {
  1141. return this->Then([Continuation = MoveTemp(Continuation)](TWwiseFuture<InternalResultType> Self) mutable
  1142. {
  1143. return Continuation(Self.Get());
  1144. });
  1145. }
  1146. /** Helper to create and immediately fulfill a promise */
  1147. template<typename ResultType, typename... ArgTypes>
  1148. TWwisePromise<ResultType> MakeFulfilledWwisePromise(ArgTypes&&... Args)
  1149. {
  1150. TWwisePromise<ResultType> Promise;
  1151. Promise.EmplaceValue(Forward<ArgTypes>(Args)...);
  1152. return Promise;
  1153. }