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