EnTT  3.10.0
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 "../config/config.h"
8 
9 namespace entt {
10 
70 template<typename Derived, typename Delta>
71 class process {
72  enum class state : std::uint8_t {
73  uninitialized = 0,
74  running,
75  paused,
76  succeeded,
77  failed,
78  aborted,
79  finished,
80  rejected
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 ENTT_NOEXCEPT {}
114 
115 protected:
122  void succeed() ENTT_NOEXCEPT {
123  if(alive()) {
124  current = state::succeeded;
125  }
126  }
127 
134  void fail() ENTT_NOEXCEPT {
135  if(alive()) {
136  current = state::failed;
137  }
138  }
139 
146  void pause() ENTT_NOEXCEPT {
147  if(current == state::running) {
148  current = state::paused;
149  }
150  }
151 
158  void unpause() ENTT_NOEXCEPT {
159  if(current == state::paused) {
160  current = state::running;
161  }
162  }
163 
164 public:
166  using delta_type = Delta;
167 
169  virtual ~process() ENTT_NOEXCEPT {
170  static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template");
171  }
172 
181  void abort(const bool immediately = false) {
182  if(alive()) {
183  current = state::aborted;
184 
185  if(immediately) {
186  tick({});
187  }
188  }
189  }
190 
195  [[nodiscard]] bool alive() const ENTT_NOEXCEPT {
196  return current == state::running || current == state::paused;
197  }
198 
203  [[nodiscard]] bool finished() const ENTT_NOEXCEPT {
204  return current == state::finished;
205  }
206 
211  [[nodiscard]] bool paused() const ENTT_NOEXCEPT {
212  return current == state::paused;
213  }
214 
219  [[nodiscard]] bool rejected() const ENTT_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 
262 private:
263  state current{state::uninitialized};
264 };
265 
305 template<typename Func, typename Delta>
306 struct 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 alive() const
Returns true if a process is either running or paused.
Definition: process.hpp:195
virtual ~process()
Default destructor.
Definition: process.hpp:169
void succeed()
Terminates a process with success if it's still alive.
Definition: process.hpp:122
void fail()
Terminates a process with errors if it's still alive.
Definition: process.hpp:134
void pause()
Stops a process if it's in a running state.
Definition: process.hpp:146
bool finished() const
Returns true if a process is already terminated.
Definition: process.hpp:203
Delta delta_type
Type used to provide elapsed time.
Definition: process.hpp:166
bool paused() const
Returns true if a process is currently paused.
Definition: process.hpp:211
void unpause()
Restarts a process if it's paused.
Definition: process.hpp:158
bool rejected() const
Returns true if a process terminated with errors.
Definition: process.hpp:219
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 immediately=false)
Aborts a process if it's still alive.
Definition: process.hpp:181
EnTT default namespace.
Definition: dense_map.hpp:22
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