Skip to content

Commit

Permalink
Merge branch 'remove_groups' of https://github.com/kgorking/ecs into …
Browse files Browse the repository at this point in the history
…remove_groups
  • Loading branch information
kgorking committed Nov 22, 2023
2 parents da53e73 + 5ff7c27 commit 9a73a84
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 166 deletions.
99 changes: 16 additions & 83 deletions include/ecs/ecs.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -1265,20 +1265,6 @@ private:

namespace ecs::detail {

//
// Check if type is a group
template <typename T>
struct is_group {
static constexpr bool value = false;
};
template <typename T>
requires requires {
T::group_id;
}
struct is_group<T> {
static constexpr bool value = true;
};

//
// Check if type is an interval
template <typename T>
Expand Down Expand Up @@ -2850,11 +2836,6 @@ private:
#define ECS_OPTIONS_H

ECS_EXPORT namespace ecs::opts {
template <int I>
struct group {
static constexpr int group_id = I;
};

template <int Milliseconds, int Microseconds = 0>
struct interval {
static_assert(Milliseconds >= 0, "time values can not be negative");
Expand Down Expand Up @@ -3445,9 +3426,6 @@ public:
return enabled;
}

// Returns the group this system belongs to
[[nodiscard]] virtual int get_group() const noexcept = 0;

// Get the hashes of types used by the system with const/reference qualifiers removed
[[nodiscard]] virtual std::span<detail::type_hash const> get_type_hashes() const noexcept = 0;

Expand Down Expand Up @@ -3520,11 +3498,6 @@ public:
}
}

constexpr int get_group() const noexcept override {
using group = test_option_type_or<is_group, Options, opts::group<0>>;
return group::group_id;
}

constexpr std::span<detail::type_hash const> get_type_hashes() const noexcept override {
return type_hashes;
}
Expand Down Expand Up @@ -4166,65 +4139,26 @@ private:

// Schedules systems for concurrent execution based on their components.
class scheduler final {
// A group of systems with the same group id
struct systems_group final {
std::vector<scheduler_node> all_nodes;
std::vector<std::size_t> entry_nodes{};
int id;

systems_group() {}
systems_group(int group_id) : id(group_id) {}

// Runs the entry nodes in parallel
void run() {
std::for_each(std::execution::par, entry_nodes.begin(), entry_nodes.end(), [this](size_t node_id) {
all_nodes[node_id].run(all_nodes);
});
}
};

std::vector<systems_group> groups;

protected:
systems_group& find_group(int id) {
// Look for an existing group
if (!groups.empty()) {
for (auto& g : groups) {
if (g.id == id) {
return g;
}
}
}

// No group found, so find an insertion point
auto const insert_point = std::upper_bound(groups.begin(), groups.end(), id, [](int group_id, systems_group const& sg) {
return group_id < sg.id;
});

// Insert the group and return it
return *groups.insert(insert_point, systems_group{id});
}
std::vector<scheduler_node> all_nodes;
std::vector<std::size_t> entry_nodes{};

public:
scheduler() {}

void insert(detail::system_base* sys) {
// Find the group
auto& group = find_group(sys->get_group());

// Create a new node with the system
size_t const node_index = group.all_nodes.size();
scheduler_node& node = group.all_nodes.emplace_back(sys);
size_t const node_index = all_nodes.size();
scheduler_node& node = all_nodes.emplace_back(sys);

// Find a dependant system for each component
bool inserted = false;
auto const end = group.all_nodes.rend();
auto const end = all_nodes.rend();
for (auto const hash : sys->get_type_hashes()) {
auto it = std::next(group.all_nodes.rbegin()); // 'next' to skip the newly added system
auto it = std::next(all_nodes.rbegin()); // 'next' to skip the newly added system
while (it != end) {
scheduler_node& dep_node = *it;
// If the other system doesn't touch the same component,
// then there can be no dependecy
// then there can be no dependency
if (dep_node.get_system()->has_component(hash)) {
if (dep_node.get_system()->writes_to_component(hash) || sys->writes_to_component(hash)) {
// The system writes to the component,
Expand All @@ -4245,26 +4179,25 @@ public:

// The system has no dependencies, so make it an entry node
if (!inserted) {
group.entry_nodes.push_back(node_index);
entry_nodes.push_back(node_index);
}
}

// Clears all the schedulers data
void clear() {
groups.clear();
all_nodes.clear();
entry_nodes.clear();
}

void run() {
// Reset the execution data
for (auto& group : groups) {
for (auto& node : group.all_nodes)
node.reset_unfinished_dependencies();
}
for (auto& node : all_nodes)
node.reset_unfinished_dependencies();

// Run the groups in succession
for (auto& group : groups) {
group.run();
}
// Run the nodes concurrently
std::for_each(std::execution::par, entry_nodes.begin(), entry_nodes.end(), [this](size_t node_id) {
all_nodes[node_id].run(all_nodes);
});
}
};

Expand Down
99 changes: 16 additions & 83 deletions include/ecs/ecs_sh.h
Original file line number Diff line number Diff line change
Expand Up @@ -1265,20 +1265,6 @@ class entity_iterator {

namespace ecs::detail {

//
// Check if type is a group
template <typename T>
struct is_group {
static constexpr bool value = false;
};
template <typename T>
requires requires {
T::group_id;
}
struct is_group<T> {
static constexpr bool value = true;
};

//
// Check if type is an interval
template <typename T>
Expand Down Expand Up @@ -2850,11 +2836,6 @@ struct parent : entity_id, private std::conditional_t<(sizeof...(ParentTypes) >
#define ECS_OPTIONS_H

ECS_EXPORT namespace ecs::opts {
template <int I>
struct group {
static constexpr int group_id = I;
};

template <int Milliseconds, int Microseconds = 0>
struct interval {
static_assert(Milliseconds >= 0, "time values can not be negative");
Expand Down Expand Up @@ -3445,9 +3426,6 @@ class system_base {
return enabled;
}

// Returns the group this system belongs to
[[nodiscard]] virtual int get_group() const noexcept = 0;

// Get the hashes of types used by the system with const/reference qualifiers removed
[[nodiscard]] virtual std::span<detail::type_hash const> get_type_hashes() const noexcept = 0;

Expand Down Expand Up @@ -3520,11 +3498,6 @@ class system : public system_base {
}
}

constexpr int get_group() const noexcept override {
using group = test_option_type_or<is_group, Options, opts::group<0>>;
return group::group_id;
}

constexpr std::span<detail::type_hash const> get_type_hashes() const noexcept override {
return type_hashes;
}
Expand Down Expand Up @@ -4166,65 +4139,26 @@ struct scheduler_node final {

// Schedules systems for concurrent execution based on their components.
class scheduler final {
// A group of systems with the same group id
struct systems_group final {
std::vector<scheduler_node> all_nodes;
std::vector<std::size_t> entry_nodes{};
int id;

systems_group() {}
systems_group(int group_id) : id(group_id) {}

// Runs the entry nodes in parallel
void run() {
std::for_each(std::execution::par, entry_nodes.begin(), entry_nodes.end(), [this](size_t node_id) {
all_nodes[node_id].run(all_nodes);
});
}
};

std::vector<systems_group> groups;

protected:
systems_group& find_group(int id) {
// Look for an existing group
if (!groups.empty()) {
for (auto& g : groups) {
if (g.id == id) {
return g;
}
}
}

// No group found, so find an insertion point
auto const insert_point = std::upper_bound(groups.begin(), groups.end(), id, [](int group_id, systems_group const& sg) {
return group_id < sg.id;
});

// Insert the group and return it
return *groups.insert(insert_point, systems_group{id});
}
std::vector<scheduler_node> all_nodes;
std::vector<std::size_t> entry_nodes{};

public:
scheduler() {}

void insert(detail::system_base* sys) {
// Find the group
auto& group = find_group(sys->get_group());

// Create a new node with the system
size_t const node_index = group.all_nodes.size();
scheduler_node& node = group.all_nodes.emplace_back(sys);
size_t const node_index = all_nodes.size();
scheduler_node& node = all_nodes.emplace_back(sys);

// Find a dependant system for each component
bool inserted = false;
auto const end = group.all_nodes.rend();
auto const end = all_nodes.rend();
for (auto const hash : sys->get_type_hashes()) {
auto it = std::next(group.all_nodes.rbegin()); // 'next' to skip the newly added system
auto it = std::next(all_nodes.rbegin()); // 'next' to skip the newly added system
while (it != end) {
scheduler_node& dep_node = *it;
// If the other system doesn't touch the same component,
// then there can be no dependecy
// then there can be no dependency
if (dep_node.get_system()->has_component(hash)) {
if (dep_node.get_system()->writes_to_component(hash) || sys->writes_to_component(hash)) {
// The system writes to the component,
Expand All @@ -4245,26 +4179,25 @@ class scheduler final {

// The system has no dependencies, so make it an entry node
if (!inserted) {
group.entry_nodes.push_back(node_index);
entry_nodes.push_back(node_index);
}
}

// Clears all the schedulers data
void clear() {
groups.clear();
all_nodes.clear();
entry_nodes.clear();
}

void run() {
// Reset the execution data
for (auto& group : groups) {
for (auto& node : group.all_nodes)
node.reset_unfinished_dependencies();
}
for (auto& node : all_nodes)
node.reset_unfinished_dependencies();

// Run the groups in succession
for (auto& group : groups) {
group.run();
}
// Run the nodes concurrently
std::for_each(std::execution::par, entry_nodes.begin(), entry_nodes.end(), [this](size_t node_id) {
all_nodes[node_id].run(all_nodes);
});
}
};

Expand Down

0 comments on commit 9a73a84

Please sign in to comment.