EnTT: src/entt/process/scheduler.hpp Source File

EnTT 3.15.0

Loading...
Searching...
No Matches
scheduler.hpp
1#ifndef ENTT_PROCESS_SCHEDULER_HPP
2#define ENTT_PROCESS_SCHEDULER_HPP
3
4#include <cstddef>
5#include <memory>
6#include <type_traits>
7#include <utility>
8#include <vector>
9#include "../config/config.h"
10#include "../core/compressed_pair.hpp"
11#include "fwd.hpp"
12#include "process.hpp"
13
14namespace entt {
15
17namespace internal {
18
19template<typename Delta>
20struct basic_process_handler {
21 virtual ~basic_process_handler() = default;
22
23 virtual bool update(Delta, void *) = 0;
24 virtual void abort(bool) = 0;
25
26 // std::shared_ptr because of its type erased allocator which is useful here
27 std::shared_ptr<basic_process_handler> next;
28};
29
30template<typename Delta, typename Type>
31struct process_handler final: basic_process_handler<Delta> {
32 template<typename... Args>
33 process_handler(Args &&...args)
34 : process{std::forward<Args>(args)...} {}
35
36 bool update(const Delta delta, void *data) override {
37 if(process.tick(delta, data); process.rejected()) {
38 this->next.reset();
39 }
40
41 return (process.rejected() || process.finished());
42 }
43
44 void abort(const bool immediate) override {
45 process.abort(immediate);
46 }
47
48 Type process;
49};
50
51} // namespace internal
53
81template<typename Delta, typename Allocator>
82 class basic_scheduler {
83 template<typename Type>
84 using handler_type = internal::process_handler<Delta, Type>;
85
86 // std::shared_ptr because of its type erased allocator which is useful here
87 using process_type = std::shared_ptr<internal::basic_process_handler<Delta>>;
88
89 using alloc_traits = std::allocator_traits<Allocator>;
90 using container_allocator = typename alloc_traits::template rebind_alloc<process_type>;
91 using container_type = std::vector<process_type, container_allocator>;
92
93public:
95 using allocator_type = Allocator;
97 using size_type = std::size_t;
99 using delta_type = Delta;
100
102 basic_scheduler()
103 : basic_scheduler{allocator_type{}} {}
104
109 explicit basic_scheduler(const allocator_type &allocator)
110 : handlers{allocator, allocator} {}
111
113 basic_scheduler(const basic_scheduler &) = delete;
114
119 basic_scheduler(basic_scheduler &&other) noexcept
120 : handlers{std::move(other.handlers)} {}
121
127 basic_scheduler(basic_scheduler &&other, const allocator_type &allocator)
128 : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} {
129 ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
130 }
131
133 ~basic_scheduler() = default;
134
139 basic_scheduler &operator=(const basic_scheduler &) = delete;
140
146 basic_scheduler &operator=(basic_scheduler &&other) noexcept {
147 ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
148 swap(other);
149 return *this;
150 }
151
156 void swap(basic_scheduler &other) noexcept {
157 using std::swap;
158 swap(handlers, other.handlers);
159 }
160
165 [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
166 return handlers.second();
167 }
168
173 [[nodiscard]] size_type size() const noexcept {
174 return handlers.first().size();
175 }
176
181 [[nodiscard]] bool empty() const noexcept {
182 return handlers.first().empty();
183 }
184
191 void clear() {
192 handlers.first().clear();
193 }
194
220 template<typename Proc, typename... Args>
221 basic_scheduler &attach(Args &&...args) {
222 static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
223 auto &ref = handlers.first().emplace_back(std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...));
224 // forces the process to exit the uninitialized state
225 ref->update({}, nullptr);
226 return *this;
227 }
228
280 template<typename Func>
281 basic_scheduler &attach(Func &&func) {
282 using Proc = process_adaptor<std::decay_t<Func>, Delta>;
283 return attach<Proc>(std::forward<Func>(func));
284 }
285
293 template<typename Proc, typename... Args>
294 basic_scheduler &then(Args &&...args) {
295 static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
296 ENTT_ASSERT(!handlers.first().empty(), "Process not available");
297 auto *curr = handlers.first().back().get();
298 for(; curr->next; curr = curr->next.get()) {}
299 curr->next = std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...);
300 return *this;
301 }
302
309 template<typename Func>
310 basic_scheduler &then(Func &&func) {
311 using Proc = process_adaptor<std::decay_t<Func>, Delta>;
312 return then<Proc>(std::forward<Func>(func));
313 }
314
326 void update(const delta_type delta, void *data = nullptr) {
327 for(auto next = handlers.first().size(); next; --next) {
328 if(const auto pos = next - 1u; handlers.first()[pos]->update(delta, data)) {
329 // updating might spawn/reallocate, cannot hold refs until here
330 if(auto &curr = handlers.first()[pos]; curr->next) {
331 curr = std::move(curr->next);
332 // forces the process to exit the uninitialized state
333 curr->update({}, nullptr);
334 } else {
335 curr = std::move(handlers.first().back());
336 handlers.first().pop_back();
337 }
338 }
339 }
340 }
341
352 void abort(const bool immediate = false) {
353 for(auto &&curr: handlers.first()) {
354 curr->abort(immediate);
355 }
356 }
357
358private:
359 compressed_pair<container_type, allocator_type> handlers;
360};
361
362} // namespace entt
363
364#endif
entt::basic_scheduler::empty
bool empty() const noexcept
Returns true if at least a process is currently scheduled.
Definition scheduler.hpp:181
entt::basic_scheduler::basic_scheduler
basic_scheduler(const basic_scheduler &)=delete
Default copy constructor, deleted on purpose.
entt::basic_scheduler<>::allocator_type
Allocator allocator_type
Definition scheduler.hpp:95
entt::basic_scheduler::basic_scheduler
basic_scheduler()
Default constructor.
Definition scheduler.hpp:102
entt::basic_scheduler::size
size_type size() const noexcept
Number of processes currently scheduled.
Definition scheduler.hpp:173
entt::basic_scheduler::operator=
basic_scheduler & operator=(const basic_scheduler &)=delete
Default copy assignment operator, deleted on purpose.
entt::basic_scheduler::basic_scheduler
basic_scheduler(basic_scheduler &&other) noexcept
Move constructor.
Definition scheduler.hpp:119
entt::basic_scheduler::then
basic_scheduler & then(Func &&func)
Sets a process as a continuation of the last scheduled process.
Definition scheduler.hpp:310
entt::basic_scheduler<>::size_type
std::size_t size_type
Definition scheduler.hpp:97
entt::basic_scheduler::basic_scheduler
basic_scheduler(const allocator_type &allocator)
Constructs a scheduler with a given allocator.
Definition scheduler.hpp:109
entt::basic_scheduler::~basic_scheduler
~basic_scheduler()=default
Default destructor.
entt::basic_scheduler::operator=
basic_scheduler & operator=(basic_scheduler &&other) noexcept
Move assignment operator.
Definition scheduler.hpp:146
entt::basic_scheduler::then
basic_scheduler & then(Args &&...args)
Sets a process as a continuation of the last scheduled process.
Definition scheduler.hpp:294
entt::basic_scheduler::update
void update(const delta_type delta, void *data=nullptr)
Updates all scheduled processes.
Definition scheduler.hpp:326
entt::basic_scheduler::basic_scheduler
basic_scheduler(basic_scheduler &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition scheduler.hpp:127
entt::basic_scheduler::abort
void abort(const bool immediate=false)
Aborts all scheduled processes.
Definition scheduler.hpp:352
entt::basic_scheduler::get_allocator
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
Definition scheduler.hpp:165
entt::basic_scheduler::attach
basic_scheduler & attach(Func &&func)
Schedules a process for the next tick.
Definition scheduler.hpp:281
entt::basic_scheduler::swap
void swap(basic_scheduler &other) noexcept
Exchanges the contents with those of a given scheduler.
Definition scheduler.hpp:156
entt::basic_scheduler::clear
void clear()
Discards all scheduled processes.
Definition scheduler.hpp:191
entt::basic_scheduler<>::delta_type
Delta delta_type
Definition scheduler.hpp:99
entt::basic_scheduler::attach
basic_scheduler & attach(Args &&...args)
Schedules a process for the next tick.
Definition scheduler.hpp:221
entt::compressed_pair
A compressed pair.
Definition compressed_pair.hpp:87
entt
EnTT default namespace.
Definition dense_map.hpp:22
entt::any_policy::ref
@ ref
Aliasing mode, the object points to a non-const element.
Definition fwd.hpp:19
entt::process_adaptor
Adaptor for lambdas and functors to turn them into processes.
Definition process.hpp:328