cesium-native  0.41.0
Future.h
1 #pragma once
2 
3 #include "Impl/AsyncSystemSchedulers.h"
4 #include "Impl/CatchFunction.h"
5 #include "Impl/ContinuationFutureType.h"
6 #include "Impl/WithTracing.h"
7 #include "SharedFuture.h"
8 #include "ThreadPool.h"
9 
10 #include <CesiumUtility/Tracing.h>
11 
12 #include <variant>
13 
14 namespace CesiumAsync {
15 
16 namespace CesiumImpl {
17 
18 template <typename R> struct ParameterizedTaskUnwrapper;
19 struct TaskUnwrapper;
20 
21 } // namespace CesiumImpl
22 
29 template <typename T> class Future final {
30 public:
34  Future(Future<T>&& rhs) noexcept
35  : _pSchedulers(std::move(rhs._pSchedulers)),
36  _task(std::move(rhs._task)) {}
37 
38  Future<T>& operator=(Future<T>&& rhs) noexcept {
39  this->_pSchedulers = std::move(rhs._pSchedulers);
40  this->_task = std::move(rhs._task);
41  return *this;
42  }
43 
44  Future(const Future<T>& rhs) = delete;
45  Future<T>& operator=(const Future<T>& rhs) = delete;
46 
65  template <typename Func>
66  CesiumImpl::ContinuationFutureType_t<Func, T>
67  thenInWorkerThread(Func&& f) && {
68  return std::move(*this).thenWithScheduler(
69  this->_pSchedulers->workerThread.immediate,
70  "waiting for worker thread",
71  std::forward<Func>(f));
72  }
73 
92  template <typename Func>
93  CesiumImpl::ContinuationFutureType_t<Func, T> thenInMainThread(Func&& f) && {
94  return std::move(*this).thenWithScheduler(
95  this->_pSchedulers->mainThread.immediate,
96  "waiting for main thread",
97  std::forward<Func>(f));
98  }
99 
116  template <typename Func>
117  CesiumImpl::ContinuationFutureType_t<Func, T> thenImmediately(Func&& f) && {
118  return CesiumImpl::ContinuationFutureType_t<Func, T>(
119  this->_pSchedulers,
120  _task.then(
121  async::inline_scheduler(),
122  CesiumImpl::WithTracing<T>::end(nullptr, std::forward<Func>(f))));
123  }
124 
143  template <typename Func>
144  CesiumImpl::ContinuationFutureType_t<Func, T>
145  thenInThreadPool(const ThreadPool& threadPool, Func&& f) && {
146  return std::move(*this).thenWithScheduler(
147  threadPool._pScheduler->immediate,
148  "waiting for thread pool thread",
149  std::forward<Func>(f));
150  }
151 
173  template <typename Func> Future<T> catchInMainThread(Func&& f) && {
174  return std::move(*this).catchWithScheduler(
175  this->_pSchedulers->mainThread.immediate,
176  std::forward<Func>(f));
177  }
178 
198  template <typename Func> Future<T> catchImmediately(Func&& f) && {
199  return std::move(*this).catchWithScheduler(
200  async::inline_scheduler(),
201  std::forward<Func>(f));
202  }
203 
216  template <typename... TPassThrough>
217  Future<std::tuple<TPassThrough..., T>>
218  thenPassThrough(TPassThrough&&... values) && {
219  return std::move(*this).thenImmediately(
220  [values = std::tuple(std::forward<TPassThrough>(values)...)](
221  T&& result) mutable {
222  return std::tuple_cat(
223  std::move(values),
224  std::make_tuple(std::move(result)));
225  });
226  }
227 
241  T wait() { return this->_task.get(); }
242 
258  return this->_pSchedulers->mainThread.dispatchUntilTaskCompletes(
259  std::move(this->_task));
260  }
261 
272  bool isReady() const { return this->_task.ready(); }
273 
284  return SharedFuture<T>(this->_pSchedulers, this->_task.share());
285  }
286 
287 private:
288  Future(
289  const std::shared_ptr<CesiumImpl::AsyncSystemSchedulers>& pSchedulers,
290  async::task<T>&& task) noexcept
291  : _pSchedulers(pSchedulers), _task(std::move(task)) {}
292 
293  template <typename Func, typename Scheduler>
294  CesiumImpl::ContinuationFutureType_t<Func, T> thenWithScheduler(
295  Scheduler& scheduler,
296  const char* tracingName,
297  Func&& f) && {
298  // It would be nice if tracingName were a template parameter instead of a
299  // function parameter, but that triggers a bug in VS2017. It was previously
300  // a bug in VS2019, too, but has been fixed there:
301  // https://developercommunity.visualstudio.com/t/internal-compiler-error-when-compiling-a-template-1/534210
302 #if CESIUM_TRACING_ENABLED
303  // When tracing is enabled, we measure the time between scheduling and
304  // dispatching of the work.
305  auto task = this->_task.then(
306  async::inline_scheduler(),
307  CesiumImpl::WithTracing<T>::begin(tracingName, std::forward<Func>(f)));
308 #else
309  auto& task = this->_task;
310 #endif
311 
312  return CesiumImpl::ContinuationFutureType_t<Func, T>(
313  this->_pSchedulers,
314  task.then(
315  scheduler,
316  CesiumImpl::WithTracing<T>::end(
317  tracingName,
318  std::forward<Func>(f))));
319  }
320 
321  template <typename Func, typename Scheduler>
322  CesiumImpl::ContinuationFutureType_t<Func, std::exception>
323  catchWithScheduler(Scheduler& scheduler, Func&& f) && {
324  return CesiumImpl::ContinuationFutureType_t<Func, std::exception>(
325  this->_pSchedulers,
326  this->_task.then(
327  async::inline_scheduler(),
328  CesiumImpl::CatchFunction<Func, T, Scheduler>{
329  scheduler,
330  std::forward<Func>(f)}));
331  }
332 
333  std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers;
334  async::task<T> _task;
335 
336  friend class AsyncSystem;
337 
338  template <typename R> friend struct CesiumImpl::ParameterizedTaskUnwrapper;
339 
340  friend struct CesiumImpl::TaskUnwrapper;
341 
342  template <typename R> friend class Future;
343  template <typename R> friend class SharedFuture;
344  template <typename R> friend class Promise;
345 };
346 
347 } // namespace CesiumAsync
A value that will be available in the future, as produced by AsyncSystem.
Definition: Future.h:29
CesiumImpl::ContinuationFutureType_t< Func, T > thenInWorkerThread(Func &&f) &&
Registers a continuation function to be invoked in a worker thread when this Future resolves,...
Definition: Future.h:67
CesiumImpl::ContinuationFutureType_t< Func, T > thenInMainThread(Func &&f) &&
Registers a continuation function to be invoked in the main thread when this Future resolves,...
Definition: Future.h:93
Future< T > catchInMainThread(Func &&f) &&
Registers a continuation function to be invoked in the main thread when this Future rejects,...
Definition: Future.h:173
Future(Future< T > &&rhs) noexcept
Move constructor.
Definition: Future.h:34
Future< T > catchImmediately(Func &&f) &&
Registers a continuation function to be invoked immediately, and invalidates this Future.
Definition: Future.h:198
Future< std::tuple< TPassThrough..., T > > thenPassThrough(TPassThrough &&... values) &&
Passes through one or more additional values to the next continuation.
Definition: Future.h:218
T wait()
Waits for the future to resolve or reject and returns the result.
Definition: Future.h:241
CesiumImpl::ContinuationFutureType_t< Func, T > thenInThreadPool(const ThreadPool &threadPool, Func &&f) &&
Registers a continuation function to be invoked in a thread pool when this Future resolves,...
Definition: Future.h:145
SharedFuture< T > share() &&
Creates a version of this future that can be shared, meaning that its value may be accessed multiple ...
Definition: Future.h:283
T waitInMainThread()
Waits for this future to resolve or reject in the main thread while also processing main-thread tasks...
Definition: Future.h:257
bool isReady() const
Determines if this future is already resolved or rejected.
Definition: Future.h:272
CesiumImpl::ContinuationFutureType_t< Func, T > thenImmediately(Func &&f) &&
Registers a continuation function to be invoked immediately in whichever thread causes the Future to ...
Definition: Future.h:117
A value that will be available in the future, as produced by AsyncSystem. Unlike Future,...
Definition: SharedFuture.h:31
A thread pool created by AsyncSystem::createThreadPool.
Definition: ThreadPool.h:18
Classes that support asynchronous operations.