Prechádzať zdrojové kódy

flow: propagate allocator to generated graph + internal rework

Michele Caini 3 rokov pred
rodič
commit
9b54ee37a6
1 zmenil súbory, kde vykonal 78 pridanie a 65 odobranie
  1. 78 65
      src/entt/graph/flow.hpp

+ 78 - 65
src/entt/graph/flow.hpp

@@ -32,6 +32,7 @@ class basic_flow {
     using task_container_type = dense_set<id_type, identity, std::equal_to<id_type>, typename alloc_traits::template rebind_alloc<id_type>>;
     using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>;
     using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<id_type>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
+    using adjacency_matrix_type = adjacency_matrix<directed_tag, typename alloc_traits::template rebind_alloc<std::size_t>>;
 
     void emplace(const id_type res, const bool is_rw) {
         ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
@@ -43,6 +44,76 @@ class basic_flow {
         deps[res].emplace_back(index.first(), is_rw);
     }
 
+    void setup_graph(adjacency_matrix_type &matrix) const {
+        for(const auto &elem: deps) {
+            const auto last = elem.second.cend();
+            auto it = elem.second.cbegin();
+
+            while(it != last) {
+                if(it->second) {
+                    // rw item
+                    if(auto curr = it++; it != last) {
+                        if(it->second) {
+                            matrix.insert(curr->first, it->first);
+                        } else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
+                            for(; it != next; ++it) {
+                                matrix.insert(curr->first, it->first);
+                                matrix.insert(it->first, next->first);
+                            }
+                        } else {
+                            for(; it != next; ++it) {
+                                matrix.insert(curr->first, it->first);
+                            }
+                        }
+                    }
+                } else {
+                    // ro item (first iteration only)
+                    if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
+                        for(; it != next; ++it) {
+                            matrix.insert(it->first, next->first);
+                        }
+                    } else {
+                        it = last;
+                    }
+                }
+            }
+        }
+    }
+
+    void transitive_closure(adjacency_matrix_type &matrix) const {
+        const auto length = matrix.size();
+
+        for(std::size_t vk{}; vk < length; ++vk) {
+            for(std::size_t vi{}; vi < length; ++vi) {
+                for(std::size_t vj{}; vj < length; ++vj) {
+                    if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) {
+                        matrix.insert(vi, vj);
+                    }
+                }
+            }
+        }
+    }
+
+    void transitive_reduction(adjacency_matrix_type &matrix) const {
+        const auto length = matrix.size();
+
+        for(std::size_t vert{}; vert < length; ++vert) {
+            matrix.erase(vert, vert);
+        }
+
+        for(std::size_t vj{}; vj < length; ++vj) {
+            for(std::size_t vi{}; vi < length; ++vi) {
+                if(matrix.contains(vi, vj)) {
+                    for(std::size_t vk{}; vk < length; ++vk) {
+                        if(matrix.contains(vj, vk)) {
+                            matrix.erase(vi, vk);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
 public:
     /*! @brief Allocator type. */
     using allocator_type = Allocator;
@@ -50,6 +121,8 @@ public:
     using size_type = std::size_t;
     /*! @brief Iterable task list. */
     using iterable = iterable_adaptor<typename task_container_type::const_iterator>;
+    /*! @brief Adjacency matrix type. */
+    using graph_type = adjacency_matrix_type;
 
     /*! @brief Default constructor. */
     basic_flow()
@@ -246,72 +319,12 @@ public:
      * @brief Generates a task graph for the current content.
      * @return The adjacency matrix of the task graph.
      */
-    [[nodiscard]] adjacency_matrix<directed_tag> graph() const {
-        const auto length = vertices.size();
-        adjacency_matrix<directed_tag> matrix{length};
-
-        // creates the adjacency matrix
-        for(const auto &elem: deps) {
-            const auto last = elem.second.cend();
-            auto it = elem.second.cbegin();
-
-            while(it != last) {
-                if(it->second) {
-                    // rw item
-                    if(auto curr = it++; it != last) {
-                        if(it->second) {
-                            matrix.insert(curr->first, it->first);
-                        } else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
-                            for(; it != next; ++it) {
-                                matrix.insert(curr->first, it->first);
-                                matrix.insert(it->first, next->first);
-                            }
-                        } else {
-                            for(; it != next; ++it) {
-                                matrix.insert(curr->first, it->first);
-                            }
-                        }
-                    }
-                } else {
-                    // ro item (first iteration only)
-                    if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
-                        for(; it != next; ++it) {
-                            matrix.insert(it->first, next->first);
-                        }
-                    } else {
-                        it = last;
-                    }
-                }
-            }
-        }
-
-        // computes the transitive closure
-        for(std::size_t vk{}; vk < length; ++vk) {
-            for(std::size_t vi{}; vi < length; ++vi) {
-                for(std::size_t vj{}; vj < length; ++vj) {
-                    if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) {
-                        matrix.insert(vi, vj);
-                    }
-                }
-            }
-        }
+    [[nodiscard]] graph_type graph() const {
+        graph_type matrix{vertices.size(), get_allocator()};
 
-        // applies the transitive reduction
-        for(std::size_t vert{}; vert < length; ++vert) {
-            matrix.erase(vert, vert);
-        }
-
-        for(std::size_t vj{}; vj < length; ++vj) {
-            for(std::size_t vi{}; vi < length; ++vi) {
-                if(matrix.contains(vi, vj)) {
-                    for(std::size_t vk{}; vk < length; ++vk) {
-                        if(matrix.contains(vj, vk)) {
-                            matrix.erase(vi, vk);
-                        }
-                    }
-                }
-            }
-        }
+        setup_graph(matrix);
+        transitive_closure(matrix);
+        transitive_reduction(matrix);
 
         return matrix;
     }