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

organizer: in/out-edges support - close #1069

Michele Caini 1 год назад
Родитель
Сommit
1e9ad0fb9c
2 измененных файлов с 138 добавлено и 65 удалено
  1. 35 15
      src/entt/entity/organizer.hpp
  2. 103 50
      test/entt/entity/organizer.cpp

+ 35 - 15
src/entt/entity/organizer.hpp

@@ -167,14 +167,14 @@ public:
     struct vertex {
         /**
          * @brief Constructs a vertex of the task graph.
-         * @param vtype True if the vertex is a top-level one, false otherwise.
          * @param data The data associated with the vertex.
-         * @param edges The indices of the children in the adjacency list.
+         * @param from List of in-edges of the vertex.
+         * @param to List of out-edges of the vertex.
          */
-        vertex(const bool vtype, vertex_data data, std::vector<std::size_t> edges)
-            : is_top_level{vtype},
-              node{std::move(data)},
-              reachable{std::move(edges)} {}
+        vertex(vertex_data data, std::vector<std::size_t> from, std::vector<std::size_t> to)
+            : node{std::move(data)},
+              in{std::move(from)},
+              out{std::move(to)} {}
 
         /**
          * @brief Fills a buffer with the type info objects for the writable
@@ -219,7 +219,7 @@ public:
          * @return True if the vertex is a top-level one, false otherwise.
          */
         bool top_level() const noexcept {
-            return is_top_level;
+            return in.empty();
         }
 
         /**
@@ -254,12 +254,28 @@ public:
             return node.payload;
         }
 
+        /**
+         * @brief Returns the list of in-edges of a vertex.
+         * @return The list of in-edges of a vertex.
+         */
+        const std::vector<std::size_t> &in_edges() const noexcept {
+            return in;
+        }
+
+        /**
+         * @brief Returns the list of out-edges of a vertex.
+         * @return The list of out-edges of a vertex.
+         */
+        const std::vector<std::size_t> &out_edges() const noexcept {
+            return out;
+        }
+
         /**
          * @brief Returns the list of nodes reachable from a given vertex.
          * @return The list of nodes reachable from the vertex.
          */
-        const std::vector<std::size_t> &children() const noexcept {
-            return reachable;
+        [[deprecated("use ::out_edges")]] const std::vector<std::size_t> &children() const noexcept {
+            return out_edges();
         }
 
         /**
@@ -272,9 +288,9 @@ public:
         }
 
     private:
-        bool is_top_level;
         vertex_data node;
-        std::vector<std::size_t> reachable;
+        std::vector<std::size_t> in;
+        std::vector<std::size_t> out;
     };
 
     /**
@@ -375,14 +391,18 @@ public:
         auto adjacency_matrix = builder.graph();
 
         for(auto curr: adjacency_matrix.vertices()) {
-            const auto iterable = adjacency_matrix.in_edges(curr);
-            std::vector<std::size_t> reachable{};
+            std::vector<std::size_t> in{};
+            std::vector<std::size_t> out{};
+
+            for(auto &&edge: adjacency_matrix.in_edges(curr)) {
+                in.push_back(edge.first);
+            }
 
             for(auto &&edge: adjacency_matrix.out_edges(curr)) {
-                reachable.push_back(edge.second);
+                out.push_back(edge.second);
             }
 
-            adjacency_list.emplace_back(iterable.cbegin() == iterable.cend(), vertices[curr], std::move(reachable));
+            adjacency_list.emplace_back(vertices[curr], std::move(in), std::move(out));
         }
 
         return adjacency_list;

+ 103 - 50
test/entt/entity/organizer.cpp

@@ -64,15 +64,25 @@ TEST(Organizer, EmplaceFreeFunction) {
     ASSERT_FALSE(graph[2u].top_level());
     ASSERT_FALSE(graph[3u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 2u);
-    ASSERT_EQ(graph[1u].children().size(), 1u);
-    ASSERT_EQ(graph[2u].children().size(), 1u);
-    ASSERT_EQ(graph[3u].children().size(), 0u);
-
-    ASSERT_EQ(graph[0u].children()[0u], 1u);
-    ASSERT_EQ(graph[0u].children()[1u], 2u);
-    ASSERT_EQ(graph[1u].children()[0u], 3u);
-    ASSERT_EQ(graph[2u].children()[0u], 3u);
+    ASSERT_EQ(graph[0u].in_edges().size(), 0u);
+    ASSERT_EQ(graph[1u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].in_edges().size(), 2u);
+
+    ASSERT_EQ(graph[1u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[2u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[3u].in_edges()[0u], 1u);
+    ASSERT_EQ(graph[3u].in_edges()[1u], 2u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 2u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].out_edges().size(), 0u);
+
+    ASSERT_EQ(graph[0u].out_edges()[0u], 1u);
+    ASSERT_EQ(graph[0u].out_edges()[1u], 2u);
+    ASSERT_EQ(graph[1u].out_edges()[0u], 3u);
+    ASSERT_EQ(graph[2u].children()[0u], 3u); // NOLINT
 
     for(auto &&vertex: graph) {
         typename entt::organizer::function_type *cb = vertex.callback();
@@ -122,14 +132,23 @@ TEST(Organizer, EmplaceMemberFunction) {
     ASSERT_FALSE(graph[2u].top_level());
     ASSERT_FALSE(graph[3u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 1u);
-    ASSERT_EQ(graph[1u].children().size(), 1u);
-    ASSERT_EQ(graph[2u].children().size(), 1u);
-    ASSERT_EQ(graph[3u].children().size(), 0u);
+    ASSERT_EQ(graph[0u].in_edges().size(), 0u);
+    ASSERT_EQ(graph[1u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].in_edges().size(), 1u);
+
+    ASSERT_EQ(graph[1u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[2u].in_edges()[0u], 1u);
+    ASSERT_EQ(graph[3u].in_edges()[0u], 2u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].out_edges().size(), 0u);
 
-    ASSERT_EQ(graph[0u].children()[0u], 1u);
-    ASSERT_EQ(graph[1u].children()[0u], 2u);
-    ASSERT_EQ(graph[2u].children()[0u], 3u);
+    ASSERT_EQ(graph[0u].out_edges()[0u], 1u);
+    ASSERT_EQ(graph[1u].out_edges()[0u], 2u);
+    ASSERT_EQ(graph[2u].children()[0u], 3u); // NOLINT
 
     for(auto &&vertex: graph) {
         typename entt::organizer::function_type *cb = vertex.callback();
@@ -185,16 +204,24 @@ TEST(Organizer, EmplaceFreeFunctionWithPayload) {
     ASSERT_FALSE(graph[3u].top_level());
     ASSERT_FALSE(graph[4u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 1u);
-    ASSERT_EQ(graph[1u].children().size(), 1u);
-    ASSERT_EQ(graph[2u].children().size(), 1u);
-    ASSERT_EQ(graph[3u].children().size(), 1u);
-    ASSERT_EQ(graph[4u].children().size(), 0u);
+    ASSERT_EQ(graph[3u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[4u].in_edges().size(), 3u);
+
+    ASSERT_EQ(graph[3u].in_edges()[0u], 2u);
+    ASSERT_EQ(graph[4u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[4u].in_edges()[1u], 1u);
+    ASSERT_EQ(graph[4u].in_edges()[2u], 3u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[4u].out_edges().size(), 0u);
 
-    ASSERT_EQ(graph[0u].children()[0u], 4u);
-    ASSERT_EQ(graph[1u].children()[0u], 4u);
-    ASSERT_EQ(graph[2u].children()[0u], 3u);
-    ASSERT_EQ(graph[3u].children()[0u], 4u);
+    ASSERT_EQ(graph[0u].out_edges()[0u], 4u);
+    ASSERT_EQ(graph[1u].out_edges()[0u], 4u);
+    ASSERT_EQ(graph[2u].out_edges()[0u], 3u);
+    ASSERT_EQ(graph[3u].children()[0u], 4u); // NOLINT
 
     for(auto &&vertex: graph) {
         typename entt::organizer::function_type *cb = vertex.callback();
@@ -261,14 +288,22 @@ TEST(Organizer, EmplaceDirectFunction) {
     ASSERT_FALSE(graph[2u].top_level());
     ASSERT_FALSE(graph[3u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 1u);
-    ASSERT_EQ(graph[1u].children().size(), 1u);
-    ASSERT_EQ(graph[2u].children().size(), 1u);
-    ASSERT_EQ(graph[3u].children().size(), 0u);
+    ASSERT_EQ(graph[1u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].in_edges().size(), 1u);
 
-    ASSERT_EQ(graph[0u].children()[0u], 1u);
-    ASSERT_EQ(graph[1u].children()[0u], 2u);
-    ASSERT_EQ(graph[2u].children()[0u], 3u);
+    ASSERT_EQ(graph[1u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[2u].in_edges()[0u], 1u);
+    ASSERT_EQ(graph[3u].in_edges()[0u], 2u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].out_edges().size(), 0u);
+
+    ASSERT_EQ(graph[0u].out_edges()[0u], 1u);
+    ASSERT_EQ(graph[1u].out_edges()[0u], 2u);
+    ASSERT_EQ(graph[2u].children()[0u], 3u); // NOLINT
 
     for(auto &&vertex: graph) {
         typename entt::organizer::function_type *cb = vertex.callback();
@@ -310,19 +345,32 @@ TEST(Organizer, SyncPoint) {
     ASSERT_FALSE(graph[4u].top_level());
     ASSERT_FALSE(graph[5u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 1u);
-    ASSERT_EQ(graph[1u].children().size(), 2u);
-    ASSERT_EQ(graph[2u].children().size(), 1u);
-    ASSERT_EQ(graph[3u].children().size(), 1u);
-    ASSERT_EQ(graph[4u].children().size(), 1u);
-    ASSERT_EQ(graph[5u].children().size(), 0u);
-
-    ASSERT_EQ(graph[0u].children()[0u], 1u);
-    ASSERT_EQ(graph[1u].children()[0u], 2u);
-    ASSERT_EQ(graph[1u].children()[1u], 3u);
-    ASSERT_EQ(graph[2u].children()[0u], 4u);
-    ASSERT_EQ(graph[3u].children()[0u], 4u);
-    ASSERT_EQ(graph[4u].children()[0u], 5u);
+    ASSERT_EQ(graph[1u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].in_edges().size(), 1u);
+    ASSERT_EQ(graph[4u].in_edges().size(), 2u);
+    ASSERT_EQ(graph[5u].in_edges().size(), 1u);
+
+    ASSERT_EQ(graph[1u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[2u].in_edges()[0u], 1u);
+    ASSERT_EQ(graph[3u].in_edges()[0u], 1u);
+    ASSERT_EQ(graph[4u].in_edges()[0u], 2u);
+    ASSERT_EQ(graph[4u].in_edges()[1u], 3u);
+    ASSERT_EQ(graph[5u].in_edges()[0u], 4u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 2u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[3u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[4u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[5u].out_edges().size(), 0u);
+
+    ASSERT_EQ(graph[0u].out_edges()[0u], 1u);
+    ASSERT_EQ(graph[1u].out_edges()[0u], 2u);
+    ASSERT_EQ(graph[1u].out_edges()[1u], 3u);
+    ASSERT_EQ(graph[2u].out_edges()[0u], 4u);
+    ASSERT_EQ(graph[3u].out_edges()[0u], 4u);
+    ASSERT_EQ(graph[4u].children()[0u], 5u); // NOLINT
 
     for(auto &&vertex: graph) {
         typename entt::organizer::function_type *cb = vertex.callback();
@@ -349,12 +397,17 @@ TEST(Organizer, Override) {
     ASSERT_TRUE(graph[1u].top_level());
     ASSERT_FALSE(graph[2u].top_level());
 
-    ASSERT_EQ(graph[0u].children().size(), 1u);
-    ASSERT_EQ(graph[1u].children().size(), 1u);
-    ASSERT_EQ(graph[2u].children().size(), 0u);
+    ASSERT_EQ(graph[2u].in_edges().size(), 2u);
+
+    ASSERT_EQ(graph[2u].in_edges()[0u], 0u);
+    ASSERT_EQ(graph[2u].in_edges()[1u], 1u);
+
+    ASSERT_EQ(graph[0u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[1u].out_edges().size(), 1u);
+    ASSERT_EQ(graph[2u].out_edges().size(), 0u);
 
-    ASSERT_EQ(graph[0u].children()[0u], 2u);
-    ASSERT_EQ(graph[1u].children()[0u], 2u);
+    ASSERT_EQ(graph[0u].out_edges()[0u], 2u);
+    ASSERT_EQ(graph[1u].children()[0u], 2u); // NOLINT
 }
 
 TEST(Organizer, Prepare) {