entt  2.3.0
process.hpp
1 #ifndef ENTT_PROCESS_PROCESS_HPP
2 #define ENTT_PROCESS_PROCESS_HPP
3 
4 
5 #include <type_traits>
6 #include <functional>
7 #include <utility>
8 
9 
10 namespace entt {
11 
12 
13 namespace {
14 
15 
16 struct BaseProcess {
17  enum class State: unsigned int {
18  UNINITIALIZED = 0,
19  RUNNING,
20  PAUSED,
21  SUCCEEDED,
22  FAILED,
23  ABORTED,
24  FINISHED
25  };
26 
27  template<State state>
28  using tag = std::integral_constant<State, state>;
29 };
30 
31 
32 }
33 
34 
84 template<typename Derived, typename Delta>
85 class Process: private BaseProcess {
86  template<typename Target = Derived>
87  auto tick(int, tag<State::UNINITIALIZED>)
88  -> decltype(std::declval<Target>().init()) {
89  static_cast<Target *>(this)->init();
90  }
91 
92  template<typename Target = Derived>
93  auto tick(int, tag<State::RUNNING>, Delta delta)
94  -> decltype(std::declval<Target>().update(delta)) {
95  static_cast<Target *>(this)->update(delta);
96  }
97 
98  template<typename Target = Derived>
99  auto tick(int, tag<State::SUCCEEDED>)
100  -> decltype(std::declval<Target>().succeeded()) {
101  static_cast<Target *>(this)->succeeded();
102  }
103 
104  template<typename Target = Derived>
105  auto tick(int, tag<State::FAILED>)
106  -> decltype(std::declval<Target>().failed()) {
107  static_cast<Target *>(this)->failed();
108  }
109 
110  template<typename Target = Derived>
111  auto tick(int, tag<State::ABORTED>)
112  -> decltype(std::declval<Target>().aborted()) {
113  static_cast<Target *>(this)->aborted();
114  }
115 
116  template<State S, typename... Args>
117  void tick(char, tag<S>, Args&&...) {}
118 
119 protected:
126  void succeed() noexcept {
127  if(alive()) {
128  current = State::SUCCEEDED;
129  }
130  }
131 
138  void fail() noexcept {
139  if(alive()) {
140  current = State::FAILED;
141  }
142  }
143 
150  void pause() noexcept {
151  if(current == State::RUNNING) {
152  current = State::PAUSED;
153  }
154  }
155 
162  void unpause() noexcept {
163  if(current == State::PAUSED) {
164  current = State::RUNNING;
165  }
166  }
167 
168 public:
170  using delta_type = Delta;
171 
173  ~Process() noexcept {
174  static_assert(std::is_base_of<Process, Derived>::value, "!");
175  }
176 
185  void abort(bool immediately = false) noexcept {
186  if(alive()) {
187  current = State::ABORTED;
188 
189  if(immediately) {
190  tick(0);
191  }
192  }
193  }
194 
199  bool alive() const noexcept {
200  return current == State::RUNNING || current == State::PAUSED;
201  }
202 
207  bool dead() const noexcept {
208  return current == State::FINISHED;
209  }
210 
215  bool paused() const noexcept {
216  return current == State::PAUSED;
217  }
218 
223  bool rejected() const noexcept {
224  return stopped;
225  }
226 
231  void tick(Delta delta) {
232  switch (current) {
233  case State::UNINITIALIZED:
234  tick(0, tag<State::UNINITIALIZED>{});
235  current = State::RUNNING;
236  // no break on purpose, tasks are executed immediately
237  case State::RUNNING:
238  tick(0, tag<State::RUNNING>{}, delta);
239  default:
240  // suppress warnings
241  break;
242  }
243 
244  // if it's dead, it must be notified and removed immediately
245  switch(current) {
246  case State::SUCCEEDED:
247  tick(0, tag<State::SUCCEEDED>{});
248  current = State::FINISHED;
249  break;
250  case State::FAILED:
251  tick(0, tag<State::FAILED>{});
252  current = State::FINISHED;
253  stopped = true;
254  break;
255  case State::ABORTED:
256  tick(0, tag<State::ABORTED>{});
257  current = State::FINISHED;
258  stopped = true;
259  break;
260  default:
261  // suppress warnings
262  break;
263  }
264  }
265 
266 private:
267  State current{State::UNINITIALIZED};
268  bool stopped{false};
269 };
270 
271 
310 template<typename Func, typename Delta>
311 struct ProcessAdaptor: Process<ProcessAdaptor<Func, Delta>, Delta>, private Func {
317  template<typename... Args>
318  ProcessAdaptor(Args&&... args)
319  : Func{std::forward<Args>(args)...}
320  {}
321 
326  void update(Delta delta) {
327  Func::operator()(delta, [this](){ this->succeed(); }, [this](){ this->fail(); });
328  }
329 };
330 
331 
332 }
333 
334 
335 #endif // ENTT_PROCESS_PROCESS_HPP
bool rejected() const noexcept
Returns true if a process terminated with errors.
Definition: process.hpp:223
void succeed() noexcept
Terminates a process with success if it&#39;s still alive.
Definition: process.hpp:126
void unpause() noexcept
Restarts a process if it&#39;s paused.
Definition: process.hpp:162
void fail() noexcept
Terminates a process with errors if it&#39;s still alive.
Definition: process.hpp:138
Base class for processes.
Definition: process.hpp:85
EnTT default namespace.
Definition: family.hpp:9
ProcessAdaptor(Args &&... args)
Constructs a process adaptor from a lambda or a functor.
Definition: process.hpp:318
void tick(Delta delta)
Updates a process and its internal state if required.
Definition: process.hpp:231
bool alive() const noexcept
Returns true if a process is either running or paused.
Definition: process.hpp:199
Adaptor for lambdas and functors to turn them into processes.
Definition: process.hpp:311
Delta delta_type
Type used to provide elapsed time.
Definition: process.hpp:170
void update(Delta delta)
Updates a process and its internal state if required.
Definition: process.hpp:326
void abort(bool immediately=false) noexcept
Aborts a process if it&#39;s still alive.
Definition: process.hpp:185
~Process() noexcept
Default destructor.
Definition: process.hpp:173
bool dead() const noexcept
Returns true if a process is already terminated.
Definition: process.hpp:207
void pause() noexcept
Stops a process if it&#39;s in a running state.
Definition: process.hpp:150
bool paused() const noexcept
Returns true if a process is currently paused.
Definition: process.hpp:215