|
|
@@ -15,18 +15,17 @@
|
|
|
|
|
|
# Introduction
|
|
|
|
|
|
-Sometimes processes are a useful tool to work around the strict definition of a
|
|
|
-system and introduce logic in a different way, usually without resorting to the
|
|
|
-introduction of other components.
|
|
|
-
|
|
|
-`EnTT` offers a minimal support to this paradigm by introducing a few classes
|
|
|
-that users can use to define and execute cooperative processes.
|
|
|
+Processes are a useful tool to work around the strict definition of a system and
|
|
|
+introduce logic in a different way, usually without resorting to other component
|
|
|
+types.<br/>
|
|
|
+`EnTT` offers minimal support to this paradigm by introducing a few classes used
|
|
|
+to define and execute cooperative processes.
|
|
|
|
|
|
# The process
|
|
|
|
|
|
-A typical process must inherit from the `process` class template that stays true
|
|
|
-to the CRTP idiom. Moreover, derived classes must specify what's the intended
|
|
|
-type for elapsed times.
|
|
|
+A typical task inherits from the `process` class template that stays true to the
|
|
|
+CRTP idiom. Moreover, derived classes specify what the intended type for elapsed
|
|
|
+times is.
|
|
|
|
|
|
A process should expose publicly the following member functions whether needed
|
|
|
(note that it isn't required to define a function unless the derived class wants
|
|
|
@@ -34,39 +33,38 @@ to _override_ the default behavior):
|
|
|
|
|
|
* `void update(Delta, void *);`
|
|
|
|
|
|
- It's invoked once per tick until a process is explicitly aborted or it
|
|
|
- terminates either with or without errors. Even though it's not mandatory to
|
|
|
- declare this member function, as a rule of thumb each process should at
|
|
|
- least define it to work properly. The `void *` parameter is an opaque pointer
|
|
|
- to user data (if any) forwarded directly to the process during an update.
|
|
|
+ This is invoked once per tick until a process is explicitly aborted or ends
|
|
|
+ either with or without errors. Even though it's not mandatory to declare this
|
|
|
+ member function, as a rule of thumb each process should at least define it to
|
|
|
+ work _properly_. The `void *` parameter is an opaque pointer to user data (if
|
|
|
+ any) forwarded directly to the process during an update.
|
|
|
|
|
|
* `void init();`
|
|
|
|
|
|
- It's invoked when the process joins the running queue of a scheduler. This
|
|
|
- happens as soon as it's attached to the scheduler if the process is a top
|
|
|
- level one, otherwise when it replaces its parent if the process is a
|
|
|
- continuation.
|
|
|
+ This is invoked when the process joins the running queue of a scheduler. It
|
|
|
+ happens usually as soon as the process is attached to the scheduler if it's a
|
|
|
+ top level one, otherwise when it replaces its parent if it's a _continuation_.
|
|
|
|
|
|
* `void succeeded();`
|
|
|
|
|
|
- It's invoked in case of success, immediately after an update and during the
|
|
|
+ This is invoked in case of success, immediately after an update and during the
|
|
|
same tick.
|
|
|
|
|
|
* `void failed();`
|
|
|
|
|
|
- It's invoked in case of errors, immediately after an update and during the
|
|
|
+ This is invoked in case of errors, immediately after an update and during the
|
|
|
same tick.
|
|
|
|
|
|
* `void aborted();`
|
|
|
|
|
|
- It's invoked only if a process is explicitly aborted. There is no guarantee
|
|
|
- that it executes in the same tick, this depends solely on whether the
|
|
|
- process is aborted immediately or not.
|
|
|
+ This is invoked only if a process is explicitly aborted. There is no guarantee
|
|
|
+ that it executes in the same tick, it depends solely on whether the process is
|
|
|
+ aborted immediately or not.
|
|
|
|
|
|
Derived classes can also change the internal state of a process by invoking
|
|
|
-`succeed` and `fail`, as well as `pause` and `unpause` the process itself. All
|
|
|
-these are protected member functions made available to be able to manage the
|
|
|
-life cycle of a process from a derived class.
|
|
|
+`succeed` and `fail`, as well as `pause` and `unpause` the process itself.<br/>
|
|
|
+All these are protected member functions made available to manage the life cycle
|
|
|
+of a process from a derived class.
|
|
|
|
|
|
Here is a minimal example for the sake of curiosity:
|
|
|
|
|
|
@@ -95,14 +93,14 @@ private:
|
|
|
|
|
|
## Adaptor
|
|
|
|
|
|
-Lambdas and functors can't be used directly with a scheduler for they are not
|
|
|
+Lambdas and functors can't be used directly with a scheduler because they aren't
|
|
|
properly defined processes with managed life cycles.<br/>
|
|
|
This class helps in filling the gap and turning lambdas and functors into
|
|
|
full-featured processes usable by a scheduler.
|
|
|
|
|
|
The function call operator has a signature similar to the one of the `update`
|
|
|
-function of a process but for the fact that it receives two extra arguments to
|
|
|
-call whenever a process is terminated with success or with an error:
|
|
|
+function of a process but for the fact that it receives two extra callbacks to
|
|
|
+invoke whenever a process terminates with success or with an error:
|
|
|
|
|
|
```cpp
|
|
|
void(Delta delta, void *data, auto succeed, auto fail);
|
|
|
@@ -127,9 +125,9 @@ A cooperative scheduler runs different processes and helps managing their life
|
|
|
cycles.
|
|
|
|
|
|
Each process is invoked once per tick. If it terminates, it's removed
|
|
|
-automatically from the scheduler and it's never invoked again. Otherwise it's
|
|
|
+automatically from the scheduler and it's never invoked again. Otherwise, it's
|
|
|
a good candidate to run one more time the next tick.<br/>
|
|
|
-A process can also have a child. In this case, the parent process is replaced
|
|
|
+A process can also have a _child_. In this case, the parent process is replaced
|
|
|
with its child when it terminates and only if it returns with success. In case
|
|
|
of errors, both the parent process and its child are discarded. This way, it's
|
|
|
easy to create chain of processes to run sequentially.
|
|
|
@@ -138,18 +136,25 @@ Using a scheduler is straightforward. To create it, users must provide only the
|
|
|
type for the elapsed times and no arguments at all:
|
|
|
|
|
|
```cpp
|
|
|
-entt::scheduler<std::uint32_t> scheduler;
|
|
|
+entt::basic_scheduler<std::uint64_t> scheduler;
|
|
|
+```
|
|
|
+
|
|
|
+Otherwise, the `scheduler` alias is also available for the most common cases. It
|
|
|
+uses `std::uint32_t` as a default type:
|
|
|
+
|
|
|
+```cpp
|
|
|
+entt::scheduler scheduler;
|
|
|
```
|
|
|
|
|
|
-It has member functions to query its internal data structures, like `empty` or
|
|
|
-`size`, as well as a `clear` utility to reset it to a clean state:
|
|
|
+The class has member functions to query its internal data structures, like
|
|
|
+`empty` or `size`, as well as a `clear` utility to reset it to a clean state:
|
|
|
|
|
|
```cpp
|
|
|
// checks if there are processes still running
|
|
|
const auto empty = scheduler.empty();
|
|
|
|
|
|
// gets the number of processes still running
|
|
|
-entt::scheduler<std::uint32_t>::size_type size = scheduler.size();
|
|
|
+entt::scheduler::size_type size = scheduler.size();
|
|
|
|
|
|
// resets the scheduler to its initial state and discards all the processes
|
|
|
scheduler.clear();
|
|
|
@@ -173,7 +178,7 @@ To attach a process to a scheduler there are mainly two ways:
|
|
|
```
|
|
|
|
|
|
In both cases, the return value is an opaque object that offers a `then` member
|
|
|
-function to use to create chains of processes to run sequentially.<br/>
|
|
|
+function used to create chains of processes to run sequentially.<br/>
|
|
|
As a minimal example of use:
|
|
|
|
|
|
```cpp
|
|
|
@@ -201,7 +206,7 @@ scheduler.update(delta, &data);
|
|
|
```
|
|
|
|
|
|
In addition to these functions, the scheduler offers an `abort` member function
|
|
|
-that can be used to discard all the running processes at once:
|
|
|
+that is used to discard all the running processes at once:
|
|
|
|
|
|
```cpp
|
|
|
// aborts all the processes abruptly ...
|