EnTT 3.13.0
Loading...
Searching...
No Matches
process.hpp
1#ifndef ENTT_PROCESS_PROCESS_HPP
2#define ENTT_PROCESS_PROCESS_HPP
3
4#include <cstdint>
5#include <type_traits>
6#include <utility>
7#include "fwd.hpp"
8
9namespace entt {
10
70template<typename Derived, typename Delta>
71class process {
72 enum class state : std::uint8_t {
73 uninitialized = 0,
74 running,
75 paused,
76 succeeded,
77 failed,
78 aborted,
81 };
82
83 template<typename Target = Derived>
84 auto next(std::integral_constant<state, state::uninitialized>)
85 -> decltype(std::declval<Target>().init(), void()) {
86 static_cast<Target *>(this)->init();
87 }
88
89 template<typename Target = Derived>
90 auto next(std::integral_constant<state, state::running>, Delta delta, void *data)
91 -> decltype(std::declval<Target>().update(delta, data), void()) {
92 static_cast<Target *>(this)->update(delta, data);
93 }
94
95 template<typename Target = Derived>
96 auto next(std::integral_constant<state, state::succeeded>)
97 -> decltype(std::declval<Target>().succeeded(), void()) {
98 static_cast<Target *>(this)->succeeded();
99 }
100
101 template<typename Target = Derived>
102 auto next(std::integral_constant<state, state::failed>)
103 -> decltype(std::declval<Target>().failed(), void()) {
104 static_cast<Target *>(this)->failed();
105 }
106
107 template<typename Target = Derived>
108 auto next(std::integral_constant<state, state::aborted>)
109 -> decltype(std::declval<Target>().aborted(), void()) {
110 static_cast<Target *>(this)->aborted();
111 }
112
113 void next(...) const noexcept {}
114
115protected:
122 void succeed() noexcept {
123 if(alive()) {
124 current = state::succeeded;
125 }
126 }
127
134 void fail() noexcept {
135 if(alive()) {
136 current = state::failed;
137 }
138 }
139
146 void pause() noexcept {
147 if(current == state::running) {
148 current = state::paused;
149 }
150 }
151
158 void unpause() noexcept {
159 if(current == state::paused) {
160 current = state::running;
161 }
162 }
163
164public:
166 using delta_type = Delta;
167
169 virtual ~process() noexcept {
170 static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template");
171 }
172
181 void abort(const bool immediate = false) {
182 if(alive()) {
183 current = state::aborted;
184
185 if(immediate) {
186 tick({});
187 }
188 }
189 }
190
195 [[nodiscard]] bool alive() const noexcept {
196 return current == state::running || current == state::paused;
197 }
198
203 [[nodiscard]] bool finished() const noexcept {
204 return current == state::finished;
205 }
206
211 [[nodiscard]] bool paused() const noexcept {
212 return current == state::paused;
213 }
214
219 [[nodiscard]] bool rejected() const noexcept {
220 return current == state::rejected;
221 }
222
228 void tick(const Delta delta, void *data = nullptr) {
229 switch(current) {
230 case state::uninitialized:
231 next(std::integral_constant<state, state::uninitialized>{});
232 current = state::running;
233 break;
234 case state::running:
235 next(std::integral_constant<state, state::running>{}, delta, data);
236 break;
237 default:
238 // suppress warnings
239 break;
240 }
241
242 // if it's dead, it must be notified and removed immediately
243 switch(current) {
244 case state::succeeded:
245 next(std::integral_constant<state, state::succeeded>{});
246 current = state::finished;
247 break;
248 case state::failed:
249 next(std::integral_constant<state, state::failed>{});
250 current = state::rejected;
251 break;
252 case state::aborted:
253 next(std::integral_constant<state, state::aborted>{});
254 current = state::rejected;
255 break;
256 default:
257 // suppress warnings
258 break;
259 }
260 }
261
262private:
263 state current{state::uninitialized};
264};
265
305template<typename Func, typename Delta>
306struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Func {
312 template<typename... Args>
313 process_adaptor(Args &&...args)
314 : Func{std::forward<Args>(args)...} {}
315
321 void update(const Delta delta, void *data) {
322 Func::operator()(
323 delta,
324 data,
325 [this]() { this->succeed(); },
326 [this]() { this->fail(); });
327 }
328};
329
330} // namespace entt
331
332#endif
Base class for processes.
Definition process.hpp:71
bool finished() const noexcept
Returns true if a process is already terminated.
Definition process.hpp:203
void pause() noexcept
Stops a process if it's in a running state.
Definition process.hpp:146
void succeed() noexcept
Terminates a process with success if it's still alive.
Definition process.hpp:122
void unpause() noexcept
Restarts a process if it's paused.
Definition process.hpp:158
Delta delta_type
Type used to provide elapsed time.
Definition process.hpp:166
bool rejected() const noexcept
Returns true if a process terminated with errors.
Definition process.hpp:219
virtual ~process() noexcept
Default destructor.
Definition process.hpp:169
void fail() noexcept
Terminates a process with errors if it's still alive.
Definition process.hpp:134
bool alive() const noexcept
Returns true if a process is either running or paused.
Definition process.hpp:195
void tick(const Delta delta, void *data=nullptr)
Updates a process and its internal state if required.
Definition process.hpp:228
void abort(const bool immediate=false)
Aborts a process if it's still alive.
Definition process.hpp:181
bool paused() const noexcept
Returns true if a process is currently paused.
Definition process.hpp:211
EnTT default namespace.
Definition dense_map.hpp:21
Adaptor for lambdas and functors to turn them into processes.
Definition process.hpp:306
void update(const Delta delta, void *data)
Updates a process and its internal state if required.
Definition process.hpp:321
process_adaptor(Args &&...args)
Constructs a process adaptor from a lambda or a functor.
Definition process.hpp:313