entt  2.4.1
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 
62 template<typename Derived, typename Delta>
63 class Process {
64  enum class State: unsigned int {
65  UNINITIALIZED = 0,
66  RUNNING,
67  PAUSED,
68  SUCCEEDED,
69  FAILED,
70  ABORTED,
71  FINISHED
72  };
73 
74  template<State state>
75  using tag = std::integral_constant<State, state>;
76 
77  template<typename Target = Derived>
78  auto tick(int, tag<State::UNINITIALIZED>, void *data)
79  -> decltype(std::declval<Target>().init(data)) {
80  static_cast<Target *>(this)->init(data);
81  }
82 
83  template<typename Target = Derived>
84  auto tick(int, tag<State::RUNNING>, Delta delta, void *data)
85  -> decltype(std::declval<Target>().update(delta, data)) {
86  static_cast<Target *>(this)->update(delta, data);
87  }
88 
89  template<typename Target = Derived>
90  auto tick(int, tag<State::SUCCEEDED>)
91  -> decltype(std::declval<Target>().succeeded()) {
92  static_cast<Target *>(this)->succeeded();
93  }
94 
95  template<typename Target = Derived>
96  auto tick(int, tag<State::FAILED>)
97  -> decltype(std::declval<Target>().failed()) {
98  static_cast<Target *>(this)->failed();
99  }
100 
101  template<typename Target = Derived>
102  auto tick(int, tag<State::ABORTED>)
103  -> decltype(std::declval<Target>().aborted()) {
104  static_cast<Target *>(this)->aborted();
105  }
106 
107  template<State S, typename... Args>
108  void tick(char, tag<S>, Args&&...) {}
109 
110 protected:
117  void succeed() noexcept {
118  if(alive()) {
119  current = State::SUCCEEDED;
120  }
121  }
122 
129  void fail() noexcept {
130  if(alive()) {
131  current = State::FAILED;
132  }
133  }
134 
141  void pause() noexcept {
142  if(current == State::RUNNING) {
143  current = State::PAUSED;
144  }
145  }
146 
153  void unpause() noexcept {
154  if(current == State::PAUSED) {
155  current = State::RUNNING;
156  }
157  }
158 
159 public:
161  using delta_type = Delta;
162 
164  ~Process() noexcept {
165  static_assert(std::is_base_of<Process, Derived>::value, "!");
166  }
167 
176  void abort(bool immediately = false) noexcept {
177  if(alive()) {
178  current = State::ABORTED;
179 
180  if(immediately) {
181  tick(0);
182  }
183  }
184  }
185 
190  bool alive() const noexcept {
191  return current == State::RUNNING || current == State::PAUSED;
192  }
193 
198  bool dead() const noexcept {
199  return current == State::FINISHED;
200  }
201 
206  bool paused() const noexcept {
207  return current == State::PAUSED;
208  }
209 
214  bool rejected() const noexcept {
215  return stopped;
216  }
217 
223  void tick(Delta delta, void *data = nullptr) {
224  switch (current) {
225  case State::UNINITIALIZED:
226  tick(0, tag<State::UNINITIALIZED>{}, data);
227  current = State::RUNNING;
228  // no break on purpose, tasks are executed immediately
229  case State::RUNNING:
230  tick(0, tag<State::RUNNING>{}, delta, data);
231  default:
232  // suppress warnings
233  break;
234  }
235 
236  // if it's dead, it must be notified and removed immediately
237  switch(current) {
238  case State::SUCCEEDED:
239  tick(0, tag<State::SUCCEEDED>{});
240  current = State::FINISHED;
241  break;
242  case State::FAILED:
243  tick(0, tag<State::FAILED>{});
244  current = State::FINISHED;
245  stopped = true;
246  break;
247  case State::ABORTED:
248  tick(0, tag<State::ABORTED>{});
249  current = State::FINISHED;
250  stopped = true;
251  break;
252  default:
253  // suppress warnings
254  break;
255  }
256  }
257 
258 private:
259  State current{State::UNINITIALIZED};
260  bool stopped{false};
261 };
262 
263 
302 template<typename Func, typename Delta>
303 struct ProcessAdaptor: Process<ProcessAdaptor<Func, Delta>, Delta>, private Func {
309  template<typename... Args>
310  ProcessAdaptor(Args&&... args)
311  : Func{std::forward<Args>(args)...}
312  {}
313 
319  void update(Delta delta, void *data) {
320  Func::operator()(delta, data, [this](){ this->succeed(); }, [this](){ this->fail(); });
321  }
322 };
323 
324 
325 }
326 
327 
328 #endif // ENTT_PROCESS_PROCESS_HPP
bool rejected() const noexcept
Returns true if a process terminated with errors.
Definition: process.hpp:214
void succeed() noexcept
Terminates a process with success if it&#39;s still alive.
Definition: process.hpp:117
void unpause() noexcept
Restarts a process if it&#39;s paused.
Definition: process.hpp:153
void fail() noexcept
Terminates a process with errors if it&#39;s still alive.
Definition: process.hpp:129
Base class for processes.
Definition: process.hpp:63
EnTT default namespace.
Definition: family.hpp:9
ProcessAdaptor(Args &&... args)
Constructs a process adaptor from a lambda or a functor.
Definition: process.hpp:310
bool alive() const noexcept
Returns true if a process is either running or paused.
Definition: process.hpp:190
Adaptor for lambdas and functors to turn them into processes.
Definition: process.hpp:303
Delta delta_type
Type used to provide elapsed time.
Definition: process.hpp:161
void abort(bool immediately=false) noexcept
Aborts a process if it&#39;s still alive.
Definition: process.hpp:176
~Process() noexcept
Default destructor.
Definition: process.hpp:164
bool dead() const noexcept
Returns true if a process is already terminated.
Definition: process.hpp:198
void update(Delta delta, void *data)
Updates a process and its internal state if required.
Definition: process.hpp:319
void pause() noexcept
Stops a process if it&#39;s in a running state.
Definition: process.hpp:141
bool paused() const noexcept
Returns true if a process is currently paused.
Definition: process.hpp:206
void tick(Delta delta, void *data=nullptr)
Updates a process and its internal state if required.
Definition: process.hpp:223