Skip to content

Commit

Permalink
entity: add organizer predecessors and successors
Browse files Browse the repository at this point in the history
This change adds a `predecessors` method to the vertices returned from
the `oragnizer::build` method. The `children` of a vertex are also
renamed to `successors` for consistency. The existing `children` method
still exists for backwards compatibility.
  • Loading branch information
cjhowedev committed Sep 20, 2023
1 parent 6ee64d1 commit 5300629
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 61 deletions.
44 changes: 34 additions & 10 deletions src/entt/entity/organizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,13 @@ class basic_organizer final {
* @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 edges The indices of the dependencies in the adjacency list.
*/
vertex(const bool vtype, vertex_data data, std::vector<std::size_t> edges)
: is_top_level{vtype},
vertex(vertex_data data, std::vector<std::size_t> edges, std::vector<std::size_t> predecessors)
: is_top_level{predecessors.empty()},
node{std::move(data)},
reachable{std::move(edges)} {}
successors_vec{std::move(edges)},
predecessors_vec{std::move(predecessors)} {}

/**
* @brief Fills a buffer with the type info objects for the writable
Expand Down Expand Up @@ -263,11 +265,27 @@ class basic_organizer final {
}

/**
* @brief Returns the list of nodes reachable from a given vertex.
* @return The list of nodes reachable from the vertex.
* @brief Returns the list of predecessors for a given vertex.
* @return The list of predecessors' indices for the vertex.
*/
const std::vector<std::size_t> &predecessors() const noexcept {
return predecessors_vec;
}

/**
* @brief Returns the list of successors for a given vertex.
* @return The list of successors' indices for the vertex.
*/
const std::vector<std::size_t> &successors() const noexcept {
return successors_vec;
}

/**
* @brief Returns the list of successors for a given vertex.
* @return The list of successors' indices for the vertex.
*/
const std::vector<std::size_t> &children() const noexcept {
return reachable;
return successors_vec;
}

/**
Expand All @@ -282,7 +300,8 @@ class basic_organizer final {
private:
bool is_top_level;
vertex_data node;
std::vector<std::size_t> reachable;
std::vector<std::size_t> successors_vec;
std::vector<std::size_t> predecessors_vec;
};

/**
Expand Down Expand Up @@ -384,13 +403,18 @@ class basic_organizer final {

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> successors{};
std::vector<std::size_t> predecessors{};

for(auto &&edge: adjacency_matrix.in_edges(curr)) {
predecessors.push_back(edge.first);
}

for(auto &&edge: adjacency_matrix.out_edges(curr)) {
reachable.push_back(edge.second);
successors.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(successors), std::move(predecessors));
}

return adjacency_list;
Expand Down
194 changes: 143 additions & 51 deletions test/entt/entity/organizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,30 @@ 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].successors().size(), 2u);
ASSERT_EQ(graph[1u].successors().size(), 1u);
ASSERT_EQ(graph[2u].successors().size(), 1u);
ASSERT_EQ(graph[3u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 1u);
ASSERT_EQ(graph[0u].successors()[1u], 2u);
ASSERT_EQ(graph[1u].successors()[0u], 3u);
ASSERT_EQ(graph[2u].successors()[0u], 3u);

ASSERT_EQ(graph[0u].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());
ASSERT_EQ(graph[3u].successors(), graph[3u].children());

ASSERT_EQ(graph[0u].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 1u);
ASSERT_EQ(graph[2u].predecessors().size(), 1u);
ASSERT_EQ(graph[3u].predecessors().size(), 2u);

ASSERT_EQ(graph[1u].predecessors()[0u], 0u);
ASSERT_EQ(graph[2u].predecessors()[0u], 0u);
ASSERT_EQ(graph[3u].predecessors()[0u], 1u);
ASSERT_EQ(graph[3u].predecessors()[1u], 2u);

for(auto &&vertex: graph) {
ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
Expand Down Expand Up @@ -118,14 +133,28 @@ 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].successors().size(), 1u);
ASSERT_EQ(graph[1u].successors().size(), 1u);
ASSERT_EQ(graph[2u].successors().size(), 1u);
ASSERT_EQ(graph[3u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 1u);
ASSERT_EQ(graph[1u].successors()[0u], 2u);
ASSERT_EQ(graph[2u].successors()[0u], 3u);

ASSERT_EQ(graph[0u].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());
ASSERT_EQ(graph[3u].successors(), graph[3u].children());

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].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 1u);
ASSERT_EQ(graph[2u].predecessors().size(), 1u);
ASSERT_EQ(graph[3u].predecessors().size(), 1u);

ASSERT_EQ(graph[1u].predecessors()[0u], 0u);
ASSERT_EQ(graph[2u].predecessors()[0u], 1u);
ASSERT_EQ(graph[3u].predecessors()[0u], 2u);

for(auto &&vertex: graph) {
ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
Expand Down Expand Up @@ -180,16 +209,33 @@ 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[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].successors().size(), 1u);
ASSERT_EQ(graph[1u].successors().size(), 1u);
ASSERT_EQ(graph[2u].successors().size(), 1u);
ASSERT_EQ(graph[3u].successors().size(), 1u);
ASSERT_EQ(graph[4u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 4u);
ASSERT_EQ(graph[1u].successors()[0u], 4u);
ASSERT_EQ(graph[2u].successors()[0u], 3u);
ASSERT_EQ(graph[3u].successors()[0u], 4u);

ASSERT_EQ(graph[0u].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());
ASSERT_EQ(graph[3u].successors(), graph[3u].children());
ASSERT_EQ(graph[4u].successors(), graph[4u].children());

ASSERT_EQ(graph[0u].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 0u);
ASSERT_EQ(graph[2u].predecessors().size(), 0u);
ASSERT_EQ(graph[3u].predecessors().size(), 1u);
ASSERT_EQ(graph[4u].predecessors().size(), 3u);

ASSERT_EQ(graph[4u].predecessors()[0u], 0u);
ASSERT_EQ(graph[4u].predecessors()[1u], 1u);
ASSERT_EQ(graph[3u].predecessors()[0u], 2u);
ASSERT_EQ(graph[4u].predecessors()[2u], 3u);

for(auto &&vertex: graph) {
ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
Expand Down Expand Up @@ -255,14 +301,28 @@ 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[0u].successors().size(), 1u);
ASSERT_EQ(graph[1u].successors().size(), 1u);
ASSERT_EQ(graph[2u].successors().size(), 1u);
ASSERT_EQ(graph[3u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 1u);
ASSERT_EQ(graph[1u].successors()[0u], 2u);
ASSERT_EQ(graph[2u].successors()[0u], 3u);

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].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());
ASSERT_EQ(graph[3u].successors(), graph[3u].children());

ASSERT_EQ(graph[0u].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 1u);
ASSERT_EQ(graph[2u].predecessors().size(), 1u);
ASSERT_EQ(graph[3u].predecessors().size(), 1u);

ASSERT_EQ(graph[1u].predecessors()[0u], 0u);
ASSERT_EQ(graph[2u].predecessors()[0u], 1u);
ASSERT_EQ(graph[3u].predecessors()[0u], 2u);

for(auto &&vertex: graph) {
ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
Expand Down Expand Up @@ -303,19 +363,40 @@ 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[0u].successors().size(), 1u);
ASSERT_EQ(graph[1u].successors().size(), 2u);
ASSERT_EQ(graph[2u].successors().size(), 1u);
ASSERT_EQ(graph[3u].successors().size(), 1u);
ASSERT_EQ(graph[4u].successors().size(), 1u);
ASSERT_EQ(graph[5u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 1u);
ASSERT_EQ(graph[1u].successors()[0u], 2u);
ASSERT_EQ(graph[1u].successors()[1u], 3u);
ASSERT_EQ(graph[2u].successors()[0u], 4u);
ASSERT_EQ(graph[3u].successors()[0u], 4u);
ASSERT_EQ(graph[4u].successors()[0u], 5u);

ASSERT_EQ(graph[0u].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());
ASSERT_EQ(graph[3u].successors(), graph[3u].children());
ASSERT_EQ(graph[4u].successors(), graph[4u].children());
ASSERT_EQ(graph[5u].successors(), graph[5u].children());

ASSERT_EQ(graph[0u].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 1u);
ASSERT_EQ(graph[2u].predecessors().size(), 1u);
ASSERT_EQ(graph[3u].predecessors().size(), 1u);
ASSERT_EQ(graph[4u].predecessors().size(), 2u);
ASSERT_EQ(graph[5u].predecessors().size(), 1u);

ASSERT_EQ(graph[1u].predecessors()[0u], 0u);
ASSERT_EQ(graph[2u].predecessors()[0u], 1u);
ASSERT_EQ(graph[3u].predecessors()[0u], 1u);
ASSERT_EQ(graph[4u].predecessors()[0u], 2u);
ASSERT_EQ(graph[4u].predecessors()[1u], 3u);
ASSERT_EQ(graph[5u].predecessors()[0u], 4u);

for(auto &&vertex: graph) {
ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
Expand All @@ -341,12 +422,23 @@ 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[0u].successors().size(), 1u);
ASSERT_EQ(graph[1u].successors().size(), 1u);
ASSERT_EQ(graph[2u].successors().size(), 0u);

ASSERT_EQ(graph[0u].successors()[0u], 2u);
ASSERT_EQ(graph[1u].successors()[0u], 2u);

ASSERT_EQ(graph[0u].successors(), graph[0u].children());
ASSERT_EQ(graph[1u].successors(), graph[1u].children());
ASSERT_EQ(graph[2u].successors(), graph[2u].children());

ASSERT_EQ(graph[0u].predecessors().size(), 0u);
ASSERT_EQ(graph[1u].predecessors().size(), 0u);
ASSERT_EQ(graph[2u].predecessors().size(), 2u);

ASSERT_EQ(graph[0u].children()[0u], 2u);
ASSERT_EQ(graph[1u].children()[0u], 2u);
ASSERT_EQ(graph[2u].predecessors()[0u], 0u);
ASSERT_EQ(graph[2u].predecessors()[1u], 1u);
}

TEST(Organizer, Prepare) {
Expand Down

0 comments on commit 5300629

Please sign in to comment.