Просмотр исходного кода

process: prepare to redesign scheduler

Michele Caini 2 лет назад
Родитель
Сommit
a5608bf7bb
1 измененных файлов с 70 добавлено и 56 удалено
  1. 70 56
      src/entt/process/scheduler.hpp

+ 70 - 56
src/entt/process/scheduler.hpp

@@ -2,16 +2,71 @@
 #define ENTT_PROCESS_SCHEDULER_HPP
 
 #include <algorithm>
+#include <deque>
 #include <iterator>
 #include <memory>
 #include <type_traits>
 #include <utility>
-#include <vector>
 #include "fwd.hpp"
 #include "process.hpp"
 
 namespace entt {
 
+/**
+ * @cond TURN_OFF_DOXYGEN
+ * Internal details not to be documented.
+ */
+
+namespace internal {
+
+template<typename Delta>
+struct process_handler {
+    using instance_type = std::unique_ptr<void, void (*)(void *)>;
+    using update_fn_type = bool(process_handler &, const Delta, void *);
+    using abort_fn_type = void(process_handler &, bool);
+    using next_type = std::unique_ptr<process_handler>;
+
+    template<typename Proc>
+    static process_handler from(Proc &&proc) {
+        return {
+            {new Proc{std::forward<Proc>(proc)}, +[](void *proc) { delete static_cast<Proc *>(proc); }},
+            +[](process_handler &handler, const Delta delta, void *data) {
+                auto *process = static_cast<Proc *>(handler.instance.get());
+                process->tick(delta, data);
+
+                if(process->rejected()) {
+                    return true;
+                } else if(process->finished()) {
+                    if(handler.next) {
+                        handler = std::move(*handler.next);
+                        // forces the process to exit the uninitialized state
+                        return handler.update(handler, {}, nullptr);
+                    }
+
+                    return true;
+                }
+
+                return false;
+            },
+            +[](process_handler &handler, const bool immediately) {
+                static_cast<Proc *>(handler.instance.get())->abort(immediately);
+            },
+            nullptr};
+    }
+
+    instance_type instance;
+    update_fn_type *update;
+    abort_fn_type *abort;
+    next_type next;
+};
+
+} // namespace internal
+
+/**
+ * Internal details not to be documented.
+ * @endcond
+ */
+
 /**
  * @brief Cooperative scheduler for processes.
  *
@@ -40,27 +95,16 @@ namespace entt {
  */
 template<typename Delta>
 class basic_scheduler {
-    struct process_handler {
-        using instance_type = std::unique_ptr<void, void (*)(void *)>;
-        using update_fn_type = bool(basic_scheduler &, std::size_t, Delta, void *);
-        using abort_fn_type = void(basic_scheduler &, std::size_t, bool);
-        using next_type = std::unique_ptr<process_handler>;
-
-        instance_type instance;
-        update_fn_type *update;
-        abort_fn_type *abort;
-        next_type next;
-    };
+    using handler_type = internal::process_handler<Delta>;
 
     struct continuation {
-        continuation(process_handler *ref) noexcept
+        continuation(handler_type *ref) noexcept
             : handler{ref} {}
 
         template<typename Proc, typename... Args>
         continuation then(Args &&...args) {
             static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
-            auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &basic_scheduler::deleter<Proc>};
-            handler->next.reset(new process_handler{std::move(proc), &basic_scheduler::update<Proc>, &basic_scheduler::abort<Proc>, nullptr});
+            handler->next.reset(new handler_type{handler_type::from(Proc{std::forward<Args>(args)...})});
             handler = handler->next.get();
             return *this;
         }
@@ -71,39 +115,9 @@ class basic_scheduler {
         }
 
     private:
-        process_handler *handler;
+        handler_type *handler;
     };
 
-    template<typename Proc>
-    [[nodiscard]] static bool update(basic_scheduler &owner, std::size_t pos, const Delta delta, void *data) {
-        auto *process = static_cast<Proc *>(owner.handlers[pos].instance.get());
-        process->tick(delta, data);
-
-        if(process->rejected()) {
-            return true;
-        } else if(process->finished()) {
-            if(auto &&handler = owner.handlers[pos]; handler.next) {
-                handler = std::move(*handler.next);
-                // forces the process to exit the uninitialized state
-                return handler.update(owner, pos, {}, nullptr);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    template<typename Proc>
-    static void abort(basic_scheduler &owner, std::size_t pos, const bool immediately) {
-        static_cast<Proc *>(owner.handlers[pos].instance.get())->abort(immediately);
-    }
-
-    template<typename Proc>
-    static void deleter(void *proc) {
-        delete static_cast<Proc *>(proc);
-    }
-
 public:
     /*! @brief Unsigned integer type. */
     using delta_type = Delta;
@@ -112,7 +126,8 @@ public:
 
     /*! @brief Default constructor. */
     basic_scheduler()
-        : handlers{} {}
+        : handlers{} {
+    }
 
     /*! @brief Default move constructor. */
     basic_scheduler(basic_scheduler &&) = default;
@@ -174,10 +189,9 @@ public:
     template<typename Proc, typename... Args>
     auto attach(Args &&...args) {
         static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
-        auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &basic_scheduler::deleter<Proc>};
-        auto &&ref = handlers.emplace_back(process_handler{std::move(proc), &basic_scheduler::update<Proc>, &basic_scheduler::abort<Proc>, nullptr});
+        auto &ref = handlers.emplace_back(handler_type::from(Proc{std::forward<Args>(args)...}));
         // forces the process to exit the uninitialized state
-        ref.update(*this, handlers.size() - 1u, {}, nullptr);
+        ref.update(ref, {}, nullptr);
         return continuation{&handlers.back()};
     }
 
@@ -251,10 +265,10 @@ public:
      */
     void update(const delta_type delta, void *data = nullptr) {
         for(auto pos = handlers.size(); pos; --pos) {
-            const auto curr = pos - 1u;
+            auto &curr = handlers[pos - 1u];
 
-            if(const auto dead = handlers[curr].update(*this, curr, delta, data); dead) {
-                std::swap(handlers[curr], handlers.back());
+            if(const auto dead = curr.update(curr, delta, data); dead) {
+                std::swap(curr, handlers.back());
                 handlers.pop_back();
             }
         }
@@ -272,13 +286,13 @@ public:
      */
     void abort(const bool immediately = false) {
         for(auto pos = handlers.size(); pos; --pos) {
-            const auto curr = pos - 1u;
-            handlers[curr].abort(*this, curr, immediately);
+            auto &curr = handlers[pos - 1u];
+            curr.abort(curr, immediately);
         }
     }
 
 private:
-    std::vector<process_handler> handlers{};
+    std::deque<handler_type> handlers{};
 };
 
 } // namespace entt