From 61e5bcef2629e2d68b805a956a96fff264d4f74d Mon Sep 17 00:00:00 2001 From: untodesu Date: Sat, 28 Jun 2025 01:59:49 +0500 Subject: Restructure dependencies and update to C++20 - Nuked static_assert from almost everywhere in the project - Nuked binary dependency support. Might add one later though - Separated dependency headers into a separate include subdirectory - Grafted a thirdpartylegalnotices.txt generator from RITEG - Pushed development snapshot version to 2126 (26th week of 2025) --- deps/include/entt/process/fwd.hpp | 20 -- deps/include/entt/process/process.hpp | 354 ------------------------------- deps/include/entt/process/scheduler.hpp | 364 -------------------------------- 3 files changed, 738 deletions(-) delete mode 100644 deps/include/entt/process/fwd.hpp delete mode 100644 deps/include/entt/process/process.hpp delete mode 100644 deps/include/entt/process/scheduler.hpp (limited to 'deps/include/entt/process') diff --git a/deps/include/entt/process/fwd.hpp b/deps/include/entt/process/fwd.hpp deleted file mode 100644 index 18847e7..0000000 --- a/deps/include/entt/process/fwd.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef ENTT_PROCESS_FWD_HPP -#define ENTT_PROCESS_FWD_HPP - -#include -#include - -namespace entt { - -template -class process; - -template> -class basic_scheduler; - -/*! @brief Alias declaration for the most common use case. */ -using scheduler = basic_scheduler<>; - -} // namespace entt - -#endif diff --git a/deps/include/entt/process/process.hpp b/deps/include/entt/process/process.hpp deleted file mode 100644 index f2692bd..0000000 --- a/deps/include/entt/process/process.hpp +++ /dev/null @@ -1,354 +0,0 @@ -#ifndef ENTT_PROCESS_PROCESS_HPP -#define ENTT_PROCESS_PROCESS_HPP - -#include -#include -#include -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Base class for processes. - * - * This class stays true to the CRTP idiom. Derived classes must specify what's - * the intended type for elapsed times.
- * A process should expose publicly the following member functions whether - * required: - * - * * @code{.cpp} - * void update(Delta, void *); - * @endcode - * - * 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. - * - * * @code{.cpp} - * void init(); - * @endcode - * - * 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. - * - * * @code{.cpp} - * void succeeded(); - * @endcode - * - * It's invoked in case of success, immediately after an update and during the - * same tick. - * - * * @code{.cpp} - * void failed(); - * @endcode - * - * It's invoked in case of errors, immediately after an update and during the - * same tick. - * - * * @code{.cpp} - * void aborted(); - * @endcode - * - * 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. - * - * Derived classes can change the internal state of a process by invoking the - * `succeed` and `fail` protected member functions and even pause or unpause the - * process itself. - * - * @sa scheduler - * - * @tparam Derived Actual type of process that extends the class template. - * @tparam Delta Type to use to provide elapsed time. - */ -template -class process { - enum class state : std::uint8_t { - uninitialized = 0, - running, - paused, - succeeded, - failed, - aborted, - finished, - rejected - }; - - template - auto next(std::integral_constant) - -> decltype(std::declval().init(), void()) { - static_cast(this)->init(); - } - - template - auto next(std::integral_constant, Delta delta, void *data) - -> decltype(std::declval().update(delta, data), void()) { - static_cast(this)->update(delta, data); - } - - template - auto next(std::integral_constant) - -> decltype(std::declval().succeeded(), void()) { - static_cast(this)->succeeded(); - } - - template - auto next(std::integral_constant) - -> decltype(std::declval().failed(), void()) { - static_cast(this)->failed(); - } - - template - auto next(std::integral_constant) - -> decltype(std::declval().aborted(), void()) { - static_cast(this)->aborted(); - } - - template - void next(Args &&...) const noexcept {} - -protected: - /** - * @brief Terminates a process with success if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - */ - void succeed() noexcept { - if(alive()) { - current = state::succeeded; - } - } - - /** - * @brief Terminates a process with errors if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - */ - void fail() noexcept { - if(alive()) { - current = state::failed; - } - } - - /** - * @brief Stops a process if it's in a running state. - * - * The function is idempotent and it does nothing if the process isn't - * running. - */ - void pause() noexcept { - if(current == state::running) { - current = state::paused; - } - } - - /** - * @brief Restarts a process if it's paused. - * - * The function is idempotent and it does nothing if the process isn't - * paused. - */ - void unpause() noexcept { - if(current == state::paused) { - current = state::running; - } - } - -public: - /*! @brief Type used to provide elapsed time. */ - using delta_type = Delta; - - /*! @brief Default constructor. */ - constexpr process() = default; - - /*! @brief Default copy constructor. */ - process(const process &) = default; - - /*! @brief Default move constructor. */ - process(process &&) noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This process. - */ - process &operator=(const process &) = default; - - /** - * @brief Default move assignment operator. - * @return This process. - */ - process &operator=(process &&) noexcept = default; - - /*! @brief Default destructor. */ - virtual ~process() noexcept { - static_assert(std::is_base_of_v, "Incorrect use of the class template"); - } - - /** - * @brief Aborts a process if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - * - * @param immediate Requests an immediate operation. - */ - void abort(const bool immediate = false) { - if(alive()) { - current = state::aborted; - - if(immediate) { - tick({}); - } - } - } - - /** - * @brief Returns true if a process is either running or paused. - * @return True if the process is still alive, false otherwise. - */ - [[nodiscard]] bool alive() const noexcept { - return current == state::running || current == state::paused; - } - - /** - * @brief Returns true if a process is already terminated. - * @return True if the process is terminated, false otherwise. - */ - [[nodiscard]] bool finished() const noexcept { - return current == state::finished; - } - - /** - * @brief Returns true if a process is currently paused. - * @return True if the process is paused, false otherwise. - */ - [[nodiscard]] bool paused() const noexcept { - return current == state::paused; - } - - /** - * @brief Returns true if a process terminated with errors. - * @return True if the process terminated with errors, false otherwise. - */ - [[nodiscard]] bool rejected() const noexcept { - return current == state::rejected; - } - - /** - * @brief Updates a process and its internal state if required. - * @param delta Elapsed time. - * @param data Optional data. - */ - void tick(const Delta delta, void *data = nullptr) { - switch(current) { - case state::uninitialized: - next(std::integral_constant{}); - current = state::running; - break; - case state::running: - next(std::integral_constant{}, delta, data); - break; - default: - // suppress warnings - break; - } - - // if it's dead, it must be notified and removed immediately - switch(current) { - case state::succeeded: - next(std::integral_constant{}); - current = state::finished; - break; - case state::failed: - next(std::integral_constant{}); - current = state::rejected; - break; - case state::aborted: - next(std::integral_constant{}); - current = state::rejected; - break; - default: - // suppress warnings - break; - } - } - -private: - state current{state::uninitialized}; -}; - -/** - * @brief Adaptor for lambdas and functors to turn them into processes. - * - * Lambdas and functors can't be used directly with a scheduler for they are not - * properly defined processes with managed life cycles.
- * This class helps in filling the gap and turning lambdas and functors into - * full featured processes usable by a scheduler. - * - * 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 - * - * Usually users shouldn't worry about creating adaptors. A scheduler will - * create them internally each and avery time a lambda or a functor is used as - * a process. - * - * @sa process - * @sa scheduler - * - * @tparam Func Actual type of process. - * @tparam Delta Type to use to provide elapsed time. - */ -template -struct process_adaptor: process, Delta>, private Func { - /** - * @brief Constructs a process adaptor from a lambda or a functor. - * @tparam Args Types of arguments to use to initialize the actual process. - * @param args Parameters to use to initialize the actual process. - */ - template - process_adaptor(Args &&...args) - : Func{std::forward(args)...} {} - - /** - * @brief Updates a process and its internal state if required. - * @param delta Elapsed time. - * @param data Optional data. - */ - void update(const Delta delta, void *data) { - Func::operator()( - delta, - data, - [this]() { this->succeed(); }, - [this]() { this->fail(); }); - } -}; - -} // namespace entt - -#endif 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 -#include -#include -#include -#include -#include "../config/config.h" -#include "../core/compressed_pair.hpp" -#include "fwd.hpp" -#include "process.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template -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 next; -}; - -template -struct process_handler final: basic_process_handler { - template - process_handler(Args &&...args) - : process{std::forward(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.
- * 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(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 -class basic_scheduler { - template - using handler_type = internal::process_handler; - - // std::shared_ptr because of its type erased allocator which is useful here - using process_type = std::shared_ptr>; - - using alloc_traits = std::allocator_traits; - using container_allocator = typename alloc_traits::template rebind_alloc; - using container_type = std::vector; - -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(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(); - * @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 - basic_scheduler &attach(Args &&...args) { - static_assert(std::is_base_of_v, Proc>, "Invalid process type"); - auto &ref = handlers.first().emplace_back(std::allocate_shared>(handlers.second(), std::forward(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.
- * 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(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 - basic_scheduler &attach(Func &&func) { - using Proc = process_adaptor, Delta>; - return attach(std::forward(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 - basic_scheduler &then(Args &&...args) { - static_assert(std::is_base_of_v, 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>(handlers.second(), std::forward(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 - basic_scheduler &then(Func &&func) { - using Proc = process_adaptor, Delta>; - return then(std::forward(func)); - } - - /** - * @brief Updates all scheduled processes. - * - * All scheduled processes are executed in no specific order.
- * 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.
- * 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 handlers; -}; - -} // namespace entt - -#endif -- cgit