cesium-native 0.43.0
Loading...
Searching...
No Matches
ImmediateScheduler.h
1#pragma once
2
3#include "cesium-async++.h"
4
5#include <CesiumUtility/Assert.h>
6
7#include <spdlog/spdlog.h>
8
9namespace CesiumAsync {
10// Begin omitting doxygen warnings for Impl namespace
12namespace CesiumImpl {
13
14template <typename TScheduler> class ImmediateScheduler {
15public:
16 explicit ImmediateScheduler(TScheduler* pScheduler) noexcept
17 : _pScheduler(pScheduler) {}
18
19 void schedule(async::task_run_handle t) {
20 // Are we already in a suitable thread?
21 std::vector<TScheduler*>& inSuitable =
22 ImmediateScheduler<TScheduler>::getSchedulersCurrentlyDispatching();
23 if (std::find(inSuitable.begin(), inSuitable.end(), this->_pScheduler) !=
24 inSuitable.end()) {
25 // Yes, run this task directly.
26 t.run();
27 } else {
28 // No, schedule this task with the deferred scheduler.
29 this->_pScheduler->schedule(std::move(t));
30 }
31 }
32
33 class SchedulerScope {
34 public:
35 SchedulerScope(TScheduler* pScheduler = nullptr) : _pScheduler(pScheduler) {
36 if (this->_pScheduler) {
37 std::vector<TScheduler*>& inSuitable =
38 ImmediateScheduler<TScheduler>::getSchedulersCurrentlyDispatching();
39 inSuitable.push_back(this->_pScheduler);
40 }
41 }
42
43 ~SchedulerScope() noexcept { this->reset(); }
44
45 SchedulerScope(SchedulerScope&& rhs) noexcept
46 : _pScheduler(rhs._pScheduler) {
47 rhs._pScheduler = nullptr;
48 }
49
50 SchedulerScope& operator=(SchedulerScope&& rhs) noexcept {
51 std::swap(this->_pScheduler, rhs._pScheduler);
52 return *this;
53 }
54
55 void reset() noexcept {
56 if (this->_pScheduler) {
57 std::vector<TScheduler*>& inSuitable =
58 ImmediateScheduler<TScheduler>::getSchedulersCurrentlyDispatching();
59 CESIUM_ASSERT(!inSuitable.empty());
60 CESIUM_ASSERT(inSuitable.back() == this->_pScheduler);
61 inSuitable.pop_back();
62
63 this->_pScheduler = nullptr;
64 }
65 }
66
67 SchedulerScope(const SchedulerScope&) = delete;
68 SchedulerScope& operator=(const SchedulerScope&) = delete;
69
70 private:
71 TScheduler* _pScheduler;
72 };
73
74 SchedulerScope scope() { return SchedulerScope(this->_pScheduler); }
75
76private:
77 TScheduler* _pScheduler;
78
79 // If a TScheduler instance is found in this thread-local vector, then the
80 // current thread has been dispatched by this scheduler and therefore we can
81 // dispatch immediately.
82 static std::vector<TScheduler*>&
83 getSchedulersCurrentlyDispatching() noexcept {
84 // We're using a static local here rather than a static field because, on
85 // at least some Linux systems (mine), with Clang 12, in a Debug build, a
86 // thread_local static field causes a SEGFAULT on access.
87 // I don't understand why (despite hours trying), but making it a static
88 // local instead solves the problem and is arguably cleaner, anyway.
89 static thread_local std::vector<TScheduler*> schedulersCurrentlyDispatching;
90 return schedulersCurrentlyDispatching;
91 }
92};
94// End omitting doxygen warnings for Impl namespace
95
96} // namespace CesiumImpl
97} // namespace CesiumAsync
Classes that support asynchronous operations.