cesium-native 0.64.0
Loading...
Searching...
No Matches
AsyncSystem.h
1#pragma once
2
3#include "Impl/ContinuationFutureType.h"
4#include "Impl/RemoveFuture.h"
5#include "Impl/WithTracing.h"
6#include "Impl/cesium-async++.h"
7
8#include <CesiumAsync/Future.h>
9#include <CesiumAsync/Library.h>
10#include <CesiumAsync/Promise.h>
11#include <CesiumAsync/ThreadPool.h>
12#include <CesiumUtility/Tracing.h>
13#include <CesiumUtility/transformTuple.h>
14
15#include <memory>
16#include <type_traits>
17
18namespace CesiumAsync {
19class ITaskProcessor;
20
21class AsyncSystem;
22
37class CESIUMASYNC_API AsyncSystem final {
38public:
45 AsyncSystem(const std::shared_ptr<ITaskProcessor>& pTaskProcessor) noexcept;
46
66 template <typename T, typename Func> Future<T> createFuture(Func&& f) const {
67 std::shared_ptr<async::event_task<T>> pEvent =
68 std::make_shared<async::event_task<T>>();
69
70 Promise<T> promise(this->_pSchedulers, pEvent);
71
72 try {
73 f(promise);
74 } catch (...) {
75 promise.reject(std::current_exception());
76 }
77
78 return Future<T>(this->_pSchedulers, pEvent->get_task());
79 }
80
94 template <typename T> Promise<T> createPromise() const {
95 return Promise<T>(
96 this->_pSchedulers,
97 std::make_shared<async::event_task<T>>());
98 }
99
115 template <typename Func>
116 CesiumImpl::ContinuationFutureType_t<Func, void>
117 runInWorkerThread(Func&& f) const {
118 static const char* tracingName = "waiting for worker thread";
119
120 CESIUM_TRACE_BEGIN_IN_TRACK(tracingName);
121
122 return CesiumImpl::ContinuationFutureType_t<Func, void>(
123 this->_pSchedulers,
124 async::spawn(
125 this->_pSchedulers->workerThread.immediate,
126 CesiumImpl::WithTracing<void>::end(
127 tracingName,
128 std::forward<Func>(f))));
129 }
130
145 template <typename Func>
146 CesiumImpl::ContinuationFutureType_t<Func, void>
147 runInMainThread(Func&& f) const {
148 static const char* tracingName = "waiting for main thread";
149
150 CESIUM_TRACE_BEGIN_IN_TRACK(tracingName);
151
152 return CesiumImpl::ContinuationFutureType_t<Func, void>(
153 this->_pSchedulers,
154 async::spawn(
155 this->_pSchedulers->mainThread.immediate,
156 CesiumImpl::WithTracing<void>::end(
157 tracingName,
158 std::forward<Func>(f))));
159 }
160
170 template <typename Func>
171 CesiumImpl::ContinuationFutureType_t<Func, void>
172 runInThreadPool(const ThreadPool& threadPool, Func&& f) const {
173 static const char* tracingName = "waiting for thread pool";
174
175 CESIUM_TRACE_BEGIN_IN_TRACK(tracingName);
176
177 return CesiumImpl::ContinuationFutureType_t<Func, void>(
178 this->_pSchedulers,
179 async::spawn(
180 threadPool._pScheduler->immediate,
181 CesiumImpl::WithTracing<void>::end(
182 tracingName,
183 std::forward<Func>(f))));
184 }
185
195 template <typename T>
197 std::conditional_t<std::is_void_v<T>, void, std::vector<T>>;
198
221 template <typename T>
222 Future<AllValueType<T>> all(std::vector<Future<T>>&& futures) const {
223 return this->all<T, Future<T>>(
224 std::forward<std::vector<Future<T>>>(futures));
225 }
226
249 template <typename T>
250 Future<AllValueType<T>> all(std::vector<SharedFuture<T>>&& futures) const {
251 return this->all<T, SharedFuture<T>>(
252 std::forward<std::vector<SharedFuture<T>>>(futures));
253 }
254
264 template <typename... Futures>
266 std::tuple<typename CesiumImpl::RemoveFuture<Futures>::type...>;
267
291 template <typename... Futures>
292 Future<AllTupleType<Futures...>> all(Futures&&... futures) const {
293 // Helper function so that we can get the `_task` member of each future and
294 // pass as a variadic pack.
295 auto getTaskFromFuture = [](auto&& future) {
296 return std::move(future._task);
297 };
298
299 using AggregateTaskType = std::tuple<
300 async::task<typename CesiumImpl::RemoveFuture<Futures>::type>...>;
301
302 async::task<AllTupleType<Futures...>> task =
303 async::when_all(getTaskFromFuture(std::forward<Futures>(futures))...)
304 .then(async::inline_scheduler(), [](AggregateTaskType&& tasks) {
306 std::move(tasks),
307 [](auto&& task) { return task.get(); });
308 });
309
310 return Future<AllTupleType<Futures...>>(
311 this->_pSchedulers,
312 std::move(task));
313 }
314
322 template <typename T> Future<T> createResolvedFuture(T&& value) const {
323 return Future<T>(
324 this->_pSchedulers,
325 async::make_task<T>(std::forward<T>(value)));
326 }
327
333 Future<void> createResolvedFuture() const {
334 return Future<void>(this->_pSchedulers, async::make_task());
335 }
336
343
355
362 using MainThreadScope = CesiumImpl::ImmediateScheduler<
363 CesiumImpl::QueuedScheduler>::SchedulerScope;
364
372
379 ThreadPool createThreadPool(int32_t numberOfThreads) const;
380
386 bool operator==(const AsyncSystem& rhs) const noexcept;
387
393 bool operator!=(const AsyncSystem& rhs) const noexcept;
394
395private:
396 // Common implementation of 'all' for both Future and SharedFuture.
397 template <typename T, typename TFutureType>
398 Future<AllValueType<T>> all(std::vector<TFutureType>&& futures) const {
399 using TTaskType = decltype(TFutureType::_task);
400 std::vector<TTaskType> tasks;
401 tasks.reserve(futures.size());
402
403 for (auto it = futures.begin(); it != futures.end(); ++it) {
404 tasks.emplace_back(std::move(it->_task));
405 }
406
407 futures.clear();
408
409 async::task<AllValueType<T>> task =
410 async::when_all(tasks.begin(), tasks.end())
411 .then(
412 async::inline_scheduler(),
413 [](std::vector<TTaskType>&& tasks) {
414 if constexpr (std::is_void_v<T>) {
415 // Tasks return void. "Get" each task so that error
416 // information is propagated.
417 for (auto it = tasks.begin(); it != tasks.end(); ++it) {
418 it->get();
419 }
420 } else {
421 // Get all the results. If any tasks rejected, we'll bail
422 // with an exception.
423 std::vector<T> results;
424 results.reserve(tasks.size());
425
426 for (auto it = tasks.begin(); it != tasks.end(); ++it) {
427 results.emplace_back(std::move(it->get()));
428 }
429 return results;
430 }
431 });
432 return Future<AllValueType<T>>(this->_pSchedulers, std::move(task));
433 }
434
435 std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers;
436
437 template <typename T> friend class Future;
438};
439} // namespace CesiumAsync
A system for managing asynchronous requests and tasks.
Definition AsyncSystem.h:37
std::tuple< typename CesiumImpl::RemoveFuture< Futures >::type... > AllTupleType
The value type of the Future returned by AsyncSystem::all(Futures&&... futures) const.
Future< T > createResolvedFuture(T &&value) const
Creates a future that is already resolved.
bool dispatchOneMainThreadTask()
Runs a single waiting task that is currently queued for the main thread. If there are no tasks waitin...
CesiumImpl::ImmediateScheduler< CesiumImpl::QueuedScheduler >::SchedulerScope MainThreadScope
An object that denotes a scope for the current thread acting as the "main thread"....
Future< AllValueType< T > > all(std::vector< SharedFuture< T > > &&futures) const
Creates a Future that resolves when every Future in a vector resolves, and rejects when any Future in...
Future< AllTupleType< Futures... > > all(Futures &&... futures) const
Creates a Future that resolves when every Future in a variadic parameter pack resolves,...
bool operator==(const AsyncSystem &rhs) const noexcept
std::conditional_t< std::is_void_v< T >, void, std::vector< T > > AllValueType
The value type of the Future returned by AsyncSystem::all(std::vector<Future<T>>&&) const.
void dispatchMainThreadTasks()
Runs all tasks that are currently queued for the main thread.
bool operator!=(const AsyncSystem &rhs) const noexcept
AsyncSystem(const std::shared_ptr< ITaskProcessor > &pTaskProcessor) noexcept
Constructs a new instance.
Future< void > createResolvedFuture() const
Creates a future that is already resolved and resolves to no value.
CesiumImpl::ContinuationFutureType_t< Func, void > runInThreadPool(const ThreadPool &threadPool, Func &&f) const
Runs a function in a thread pool, returning a Future that resolves when the function completes.
CesiumImpl::ContinuationFutureType_t< Func, void > runInWorkerThread(Func &&f) const
Runs a function in a worker thread, returning a Future that resolves when the function completes.
Promise< T > createPromise() const
Create a Promise that can be used at a later time to resolve or reject a Future.
Definition AsyncSystem.h:94
Future< T > createFuture(Func &&f) const
Creates a new Future by immediately invoking a function and giving it the opportunity to resolve or r...
Definition AsyncSystem.h:66
CesiumImpl::ContinuationFutureType_t< Func, void > runInMainThread(Func &&f) const
Runs a function in the main thread, returning a Future that resolves when the function completes.
MainThreadScope enterMainThread() const
Enters a scope in which the current thread is treated as the "mainthread". It is essential that no ot...
ThreadPool createThreadPool(int32_t numberOfThreads) const
Creates a new thread pool that can be used to run continuations.
Future< AllValueType< T > > all(std::vector< Future< T > > &&futures) const
Creates a Future that resolves when every Future in a vector resolves, and rejects when any Future in...
A value that will be available in the future, as produced by AsyncSystem.
Definition Future.h:29
When implemented by a rendering engine, allows tasks to be asynchronously executed in background thre...
A promise that can be resolved or rejected by an asynchronous task.
Definition Promise.h:19
A value that will be available in the future, as produced by AsyncSystem. Unlike Future,...
A thread pool created by AsyncSystem::createThreadPool.
Definition ThreadPool.h:19
Classes that support asynchronous operations.
auto transformTuple(Tuple &&tuple, Func &&f)
Transforms each element of a tuple by applying a function to it.