summaryrefslogtreecommitdiffstats
path: root/deps/include/entt/process/scheduler.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'deps/include/entt/process/scheduler.hpp')
-rw-r--r--deps/include/entt/process/scheduler.hpp364
1 files changed, 0 insertions, 364 deletions
diff --git a/deps/include/entt/process/scheduler.hpp b/deps/include/entt/process/scheduler.hpp
deleted file mode 100644
index 6cd27db..0000000
--- a/deps/include/entt/process/scheduler.hpp
+++ /dev/null
@@ -1,364 +0,0 @@
-#ifndef ENTT_PROCESS_SCHEDULER_HPP
-#define ENTT_PROCESS_SCHEDULER_HPP
-
-#include <cstddef>
-#include <memory>
-#include <type_traits>
-#include <utility>
-#include <vector>
-#include "../config/config.h"
-#include "../core/compressed_pair.hpp"
-#include "fwd.hpp"
-#include "process.hpp"
-
-namespace entt {
-
-/*! @cond TURN_OFF_DOXYGEN */
-namespace internal {
-
-template<typename Delta>
-struct basic_process_handler {
- virtual ~basic_process_handler() noexcept = default;
-
- virtual bool update(const Delta, void *) = 0;
- virtual void abort(const bool) = 0;
-
- // std::shared_ptr because of its type erased allocator which is useful here
- std::shared_ptr<basic_process_handler> next;
-};
-
-template<typename Delta, typename Type>
-struct process_handler final: basic_process_handler<Delta> {
- template<typename... Args>
- process_handler(Args &&...args)
- : process{std::forward<Args>(args)...} {}
-
- bool update(const Delta delta, void *data) override {
- if(process.tick(delta, data); process.rejected()) {
- this->next.reset();
- }
-
- return (process.rejected() || process.finished());
- }
-
- void abort(const bool immediate) override {
- process.abort(immediate);
- }
-
- Type process;
-};
-
-} // namespace internal
-/*! @endcond */
-
-/**
- * @brief Cooperative scheduler for processes.
- *
- * A cooperative scheduler runs processes and helps managing their life cycles.
- *
- * Each process is invoked once per tick. If a process terminates, it's
- * removed automatically from the scheduler and it's never invoked again.<br/>
- * A process can also have a child. In this case, the process is replaced with
- * its child when it terminates if it returns with success. In case of errors,
- * both the process and its child are discarded.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * }).then<my_process>(arguments...);
- * @endcode
- *
- * In order to invoke all scheduled processes, call the `update` member function
- * passing it the elapsed time to forward to the tasks.
- *
- * @sa process
- *
- * @tparam Delta Type to use to provide elapsed time.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
-template<typename Delta, typename Allocator>
-class basic_scheduler {
- template<typename Type>
- using handler_type = internal::process_handler<Delta, Type>;
-
- // std::shared_ptr because of its type erased allocator which is useful here
- using process_type = std::shared_ptr<internal::basic_process_handler<Delta>>;
-
- using alloc_traits = std::allocator_traits<Allocator>;
- using container_allocator = typename alloc_traits::template rebind_alloc<process_type>;
- using container_type = std::vector<process_type, container_allocator>;
-
-public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Unsigned integer type. */
- using delta_type = Delta;
-
- /*! @brief Default constructor. */
- basic_scheduler()
- : basic_scheduler{allocator_type{}} {}
-
- /**
- * @brief Constructs a scheduler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_scheduler(const allocator_type &allocator)
- : handlers{allocator, allocator} {}
-
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_scheduler(const basic_scheduler &) = delete;
-
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_scheduler(basic_scheduler &&other) noexcept
- : handlers{std::move(other.handlers)} {}
-
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_scheduler(basic_scheduler &&other, const allocator_type &allocator)
- : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
- }
-
- /*! @brief Default destructor. */
- ~basic_scheduler() noexcept = default;
-
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_scheduler &operator=(const basic_scheduler &) = delete;
-
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This process scheduler.
- */
- basic_scheduler &operator=(basic_scheduler &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
- handlers = std::move(other.handlers);
- return *this;
- }
-
- /**
- * @brief Exchanges the contents with those of a given scheduler.
- * @param other Scheduler to exchange the content with.
- */
- void swap(basic_scheduler &other) {
- using std::swap;
- swap(handlers, other.handlers);
- }
-
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return handlers.second();
- }
-
- /**
- * @brief Number of processes currently scheduled.
- * @return Number of processes currently scheduled.
- */
- [[nodiscard]] size_type size() const noexcept {
- return handlers.first().size();
- }
-
- /**
- * @brief Returns true if at least a process is currently scheduled.
- * @return True if there are scheduled processes, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return handlers.first().empty();
- }
-
- /**
- * @brief Discards all scheduled processes.
- *
- * Processes aren't aborted. They are discarded along with their children
- * and never executed again.
- */
- void clear() {
- handlers.first().clear();
- }
-
- /**
- * @brief Schedules a process for the next tick.
- *
- * Returned value can be used to attach a continuation for the last process.
- * The continutation is scheduled automatically when the process terminates
- * and only if the process returns with success.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * // schedules a task in the form of a process class
- * scheduler.attach<my_process>(arguments...)
- * // appends a child in the form of a lambda function
- * .then([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of another process class
- * .then<my_other_process>();
- * @endcode
- *
- * @tparam Proc Type of process to schedule.
- * @tparam Args Types of arguments to use to initialize the process.
- * @param args Parameters to use to initialize the process.
- * @return This process scheduler.
- */
- template<typename Proc, typename... Args>
- basic_scheduler &attach(Args &&...args) {
- static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
- auto &ref = handlers.first().emplace_back(std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...));
- // forces the process to exit the uninitialized state
- ref->update({}, nullptr);
- return *this;
- }
-
- /**
- * @brief Schedules a process for the next tick.
- *
- * A process can be either a lambda or a functor. The scheduler wraps both
- * of them in a process adaptor internally.<br/>
- * The signature of the function call operator should be equivalent to the
- * following:
- *
- * @code{.cpp}
- * void(Delta delta, void *data, auto succeed, auto fail);
- * @endcode
- *
- * Where:
- *
- * * `delta` is the elapsed time.
- * * `data` is an opaque pointer to user data if any, `nullptr` otherwise.
- * * `succeed` is a function to call when a process terminates with success.
- * * `fail` is a function to call when a process terminates with errors.
- *
- * The signature of the function call operator of both `succeed` and `fail`
- * is equivalent to the following:
- *
- * @code{.cpp}
- * void();
- * @endcode
- *
- * Returned value can be used to attach a continuation for the last process.
- * The continutation is scheduled automatically when the process terminates
- * and only if the process returns with success.
- *
- * Example of use (pseudocode):
- *
- * @code{.cpp}
- * // schedules a task in the form of a lambda function
- * scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of another lambda function
- * .then([](auto delta, void *, auto succeed, auto fail) {
- * // code
- * })
- * // appends a child in the form of a process class
- * .then<my_process>(arguments...);
- * @endcode
- *
- * @sa process_adaptor
- *
- * @tparam Func Type of process to schedule.
- * @param func Either a lambda or a functor to use as a process.
- * @return This process scheduler.
- */
- template<typename Func>
- basic_scheduler &attach(Func &&func) {
- using Proc = process_adaptor<std::decay_t<Func>, Delta>;
- return attach<Proc>(std::forward<Func>(func));
- }
-
- /**
- * @brief Sets a process as a continuation of the last scheduled process.
- * @tparam Proc Type of process to use as a continuation.
- * @tparam Args Types of arguments to use to initialize the process.
- * @param args Parameters to use to initialize the process.
- * @return This process scheduler.
- */
- template<typename Proc, typename... Args>
- basic_scheduler &then(Args &&...args) {
- static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
- ENTT_ASSERT(!handlers.first().empty(), "Process not available");
- auto *curr = handlers.first().back().get();
- for(; curr->next; curr = curr->next.get()) {}
- curr->next = std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...);
- return *this;
- }
-
- /**
- * @brief Sets a process as a continuation of the last scheduled process.
- * @tparam Func Type of process to use as a continuation.
- * @param func Either a lambda or a functor to use as a process.
- * @return This process scheduler.
- */
- template<typename Func>
- basic_scheduler &then(Func &&func) {
- using Proc = process_adaptor<std::decay_t<Func>, Delta>;
- return then<Proc>(std::forward<Func>(func));
- }
-
- /**
- * @brief Updates all scheduled processes.
- *
- * All scheduled processes are executed in no specific order.<br/>
- * If a process terminates with success, it's replaced with its child, if
- * any. Otherwise, if a process terminates with an error, it's removed along
- * with its child.
- *
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void update(const delta_type delta, void *data = nullptr) {
- for(auto next = handlers.first().size(); next; --next) {
- if(const auto pos = next - 1u; handlers.first()[pos]->update(delta, data)) {
- // updating might spawn/reallocate, cannot hold refs until here
- if(auto &curr = handlers.first()[pos]; curr->next) {
- curr = std::move(curr->next);
- // forces the process to exit the uninitialized state
- curr->update({}, nullptr);
- } else {
- curr = std::move(handlers.first().back());
- handlers.first().pop_back();
- }
- }
- }
- }
-
- /**
- * @brief Aborts all scheduled processes.
- *
- * Unless an immediate operation is requested, the abort is scheduled for
- * the next tick. Processes won't be executed anymore in any case.<br/>
- * Once a process is fully aborted and thus finished, it's discarded along
- * with its child, if any.
- *
- * @param immediate Requests an immediate operation.
- */
- void abort(const bool immediate = false) {
- for(auto &&curr: handlers.first()) {
- curr->abort(immediate);
- }
- }
-
-private:
- compressed_pair<container_type, allocator_type> handlers;
-};
-
-} // namespace entt
-
-#endif