cesium-native  0.41.0
SharedFuture.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 "ThreadPool.h"
8 
9 #include <CesiumUtility/Tracing.h>
10 
11 #include <type_traits>
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 
31 template <typename T> class SharedFuture final {
32 public:
51  template <typename Func>
52  CesiumImpl::ContinuationFutureType_t<Func, T> thenInWorkerThread(Func&& f) {
53  return this->thenWithScheduler(
54  this->_pSchedulers->workerThread.immediate,
55  "waiting for worker thread",
56  std::forward<Func>(f));
57  }
58 
77  template <typename Func>
78  CesiumImpl::ContinuationFutureType_t<Func, T> thenInMainThread(Func&& f) {
79  return this->thenWithScheduler(
80  this->_pSchedulers->mainThread.immediate,
81  "waiting for main thread",
82  std::forward<Func>(f));
83  }
84 
100  template <typename Func>
101  CesiumImpl::ContinuationFutureType_t<Func, T> thenImmediately(Func&& f) {
102  return CesiumImpl::ContinuationFutureType_t<Func, T>(
103  this->_pSchedulers,
104  _task.then(
105  async::inline_scheduler(),
106  CesiumImpl::WithTracingShared<T>::end(
107  nullptr,
108  std::forward<Func>(f))));
109  }
110 
129  template <typename Func>
130  CesiumImpl::ContinuationFutureType_t<Func, T>
131  thenInThreadPool(const ThreadPool& threadPool, Func&& f) {
132  return this->thenWithScheduler(
133  threadPool._pScheduler->immediate,
134  "waiting for thread pool thread",
135  std::forward<Func>(f));
136  }
137 
159  template <typename Func> Future<T> catchInMainThread(Func&& f) {
160  return this->catchWithScheduler(
161  this->_pSchedulers->mainThread.immediate,
162  std::forward<Func>(f));
163  }
164 
184  template <typename Func> Future<T> catchImmediately(Func&& f) {
185  return this->catchWithScheduler(
186  async::inline_scheduler(),
187  std::forward<Func>(f));
188  }
189 
202  template <typename... TPassThrough>
203  Future<std::tuple<TPassThrough..., T>>
204  thenPassThrough(TPassThrough&&... values) {
205  return this->thenImmediately(
206  [values = std::tuple(std::forward<TPassThrough>(values)...)](
207  const T& result) mutable {
208  return std::tuple_cat(std::move(values), std::make_tuple(result));
209  });
210  }
211 
225  template <
226  typename U = T,
227  std::enable_if_t<std::is_same_v<U, T>, int> = 0,
228  std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
229  const U& wait() const {
230  return this->_task.get();
231  }
232 
233  template <
234  typename U = T,
235  std::enable_if_t<std::is_same_v<U, T>, int> = 0,
236  std::enable_if_t<std::is_same_v<U, void>, int> = 0>
237  void wait() const {
238  this->_task.get();
239  }
240 
256  return this->_pSchedulers->mainThread.dispatchUntilTaskCompletes(
257  std::move(this->_task));
258  }
259 
270  bool isReady() const { return this->_task.ready(); }
271 
272 private:
273  SharedFuture(
274  const std::shared_ptr<CesiumImpl::AsyncSystemSchedulers>& pSchedulers,
275  async::shared_task<T>&& task) noexcept
276  : _pSchedulers(pSchedulers), _task(std::move(task)) {}
277 
278  template <typename Func, typename Scheduler>
279  CesiumImpl::ContinuationFutureType_t<Func, T>
280  thenWithScheduler(Scheduler& scheduler, const char* tracingName, Func&& f) {
281  // It would be nice if tracingName were a template parameter instead of a
282  // function parameter, but that triggers a bug in VS2017. It was previously
283  // a bug in VS2019, too, but has been fixed there:
284  // https://developercommunity.visualstudio.com/t/internal-compiler-error-when-compiling-a-template-1/534210
285 #if CESIUM_TRACING_ENABLED
286  // When tracing is enabled, we measure the time between scheduling and
287  // dispatching of the work.
288  auto task = this->_task.then(
289  async::inline_scheduler(),
290  CesiumImpl::WithTracingShared<T>::begin(
291  tracingName,
292  std::forward<Func>(f)));
293 #else
294  auto& task = this->_task;
295 #endif
296 
297  return CesiumImpl::ContinuationFutureType_t<Func, T>(
298  this->_pSchedulers,
299  task.then(
300  scheduler,
301  CesiumImpl::WithTracingShared<T>::end(
302  tracingName,
303  std::forward<Func>(f))));
304  }
305 
306  template <typename Func, typename Scheduler>
307  CesiumImpl::ContinuationFutureType_t<Func, std::exception>
308  catchWithScheduler(Scheduler& scheduler, Func&& f) {
309  return CesiumImpl::ContinuationFutureType_t<Func, std::exception>(
310  this->_pSchedulers,
311  this->_task.then(
312  async::inline_scheduler(),
313  CesiumImpl::
314  CatchFunction<Func, T, Scheduler, const async::shared_task<T>&>{
315  scheduler,
316  std::forward<Func>(f)}));
317  }
318 
319  std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers;
320  async::shared_task<T> _task;
321 
322  friend class AsyncSystem;
323 
324  template <typename R> friend struct CesiumImpl::ParameterizedTaskUnwrapper;
325 
326  friend struct CesiumImpl::TaskUnwrapper;
327 
328  template <typename R> friend class Future;
329  template <typename R> friend class SharedFuture;
330 };
331 
332 } // namespace CesiumAsync
A value that will be available in the future, as produced by AsyncSystem.
Definition: Future.h:29
A value that will be available in the future, as produced by AsyncSystem. Unlike Future,...
Definition: SharedFuture.h:31
CesiumImpl::ContinuationFutureType_t< Func, T > thenImmediately(Func &&f)
Registers a continuation function to be invoked immediately in whichever thread causes the Future to ...
Definition: SharedFuture.h:101
bool isReady() const
Determines if this future is already resolved or rejected.
Definition: SharedFuture.h:270
T waitInMainThread()
Waits for this future to resolve or reject in the main thread while also processing main-thread tasks...
Definition: SharedFuture.h:255
CesiumImpl::ContinuationFutureType_t< Func, T > thenInWorkerThread(Func &&f)
Registers a continuation function to be invoked in a worker thread when this Future resolves.
Definition: SharedFuture.h:52
Future< T > catchInMainThread(Func &&f)
Registers a continuation function to be invoked in the main thread when this Future rejects.
Definition: SharedFuture.h:159
Future< T > catchImmediately(Func &&f)
Registers a continuation function to be invoked immediately, and invalidates this Future.
Definition: SharedFuture.h:184
Future< std::tuple< TPassThrough..., T > > thenPassThrough(TPassThrough &&... values)
Passes through one or more additional values to the next continuation.
Definition: SharedFuture.h:204
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: SharedFuture.h:131
CesiumImpl::ContinuationFutureType_t< Func, T > thenInMainThread(Func &&f)
Registers a continuation function to be invoked in the main thread when this Future resolves.
Definition: SharedFuture.h:78
const U & wait() const
Waits for the future to resolve or reject and returns the result.
Definition: SharedFuture.h:229
A thread pool created by AsyncSystem::createThreadPool.
Definition: ThreadPool.h:18
Classes that support asynchronous operations.