From 2c2b0b9e38d2d1021f18df9c1875340f20fee73f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 27 Dec 2018 13:32:40 +0700 Subject: [PATCH 1/4] remove synchronization primitives (temporarily) --- ecs.hpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/ecs.hpp b/ecs.hpp index 76c7650..b5f048e 100644 --- a/ecs.hpp +++ b/ecs.hpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -680,8 +679,6 @@ namespace ecs_hpp template < typename F, typename... Cs > void for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) const; private: - mutable std::mutex mutex_; - entity_id last_entity_id_{0u}; std::vector free_entity_ids_; detail::sparse_set entity_ids_; @@ -805,7 +802,6 @@ namespace ecs_hpp namespace ecs_hpp { inline entity registry::create_entity() { - std::lock_guard guard(mutex_); if ( !free_entity_ids_.empty() ) { auto ent = entity(*this, free_entity_ids_.back()); entity_ids_.insert(ent.id()); @@ -820,7 +816,6 @@ namespace ecs_hpp } inline bool registry::destroy_entity(const entity& ent) { - std::lock_guard guard(mutex_); remove_all_components_impl_(ent); if ( entity_ids_.unordered_erase(ent.id()) ) { free_entity_ids_.push_back(ent.id()); @@ -830,13 +825,11 @@ namespace ecs_hpp } inline bool registry::is_entity_alive(const entity& ent) const noexcept { - std::lock_guard guard(mutex_); return is_entity_alive_impl_(ent); } template < typename T, typename... Args > bool registry::assign_component(const entity& ent, Args&&... args) { - std::lock_guard guard(mutex_); if ( !is_entity_alive_impl_(ent) ) { return false; } @@ -848,7 +841,6 @@ namespace ecs_hpp template < typename T > bool registry::remove_component(const entity& ent) { - std::lock_guard guard(mutex_); if ( !is_entity_alive_impl_(ent) ) { return false; } @@ -860,7 +852,6 @@ namespace ecs_hpp template < typename T > bool registry::exists_component(const entity& ent) const noexcept { - std::lock_guard guard(mutex_); if ( !is_entity_alive_impl_(ent) ) { return false; } @@ -871,13 +862,11 @@ namespace ecs_hpp } inline std::size_t registry::remove_all_components(const entity& ent) const noexcept { - std::lock_guard guard(mutex_); return remove_all_components_impl_(ent); } template < typename T > T& registry::get_component(const entity& ent) { - std::lock_guard guard(mutex_); T* component = find_component_impl_(ent); if ( component ) { return *component; @@ -887,7 +876,6 @@ namespace ecs_hpp template < typename T > const T& registry::get_component(const entity& ent) const { - std::lock_guard guard(mutex_); const T* component = find_component_impl_(ent); if ( component ) { return *component; @@ -897,13 +885,11 @@ namespace ecs_hpp template < typename T > T* registry::find_component(const entity& ent) noexcept { - std::lock_guard guard(mutex_); return find_component_impl_(ent); } template < typename T > const T* registry::find_component(const entity& ent) const noexcept { - std::lock_guard guard(mutex_); return find_component_impl_(ent); } @@ -929,7 +915,6 @@ namespace ecs_hpp template < typename T, typename F > void registry::for_each_component(F&& f) { - std::lock_guard guard(mutex_); detail::component_storage* storage = find_storage_(); if ( storage ) { storage->for_each_component(std::forward(f)); @@ -938,7 +923,6 @@ namespace ecs_hpp template < typename T, typename F > void registry::for_each_component(F&& f) const { - std::lock_guard guard(mutex_); const detail::component_storage* storage = find_storage_(); if ( storage ) { storage->for_each_component(std::forward(f)); @@ -947,19 +931,16 @@ namespace ecs_hpp template < typename... Ts, typename F > void registry::for_joined_components(F&& f) { - std::lock_guard guard(mutex_); for_joined_components_impl_(std::forward(f)); } template < typename... Ts, typename F > void registry::for_joined_components(F&& f) const { - std::lock_guard guard(mutex_); for_joined_components_impl_(std::forward(f)); } template < typename T, typename... Args > void registry::add_system(Args&&... args) { - std::lock_guard guard(mutex_); systems_.emplace_back( std::make_unique(std::forward(args)...)); } From db62454eabd94f70476e8f4cdb26de400d407f82 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 27 Dec 2018 13:42:54 +0700 Subject: [PATCH 2/4] more code coverage --- ecs_tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ecs_tests.cpp b/ecs_tests.cpp index ad3184e..b3be859 100644 --- a/ecs_tests.cpp +++ b/ecs_tests.cpp @@ -71,6 +71,7 @@ TEST_CASE("detail") { REQUIRE(s.has(42u)); REQUIRE_FALSE(s.has(84u)); + REQUIRE(s.find(42u) == s.begin()); REQUIRE(s.find_index(42u).second); REQUIRE(s.find_index(42u).first == 0u); REQUIRE(s.get_index(42u) == 0u); @@ -231,6 +232,14 @@ TEST_CASE("registry") { REQUIRE_FALSE(w.destroy_entity(e1)); REQUIRE_FALSE(w.destroy_entity(e2)); } + { + ecs::registry w; + + const auto e1 = w.create_entity(); + w.destroy_entity(e1); + const auto e2 = w.create_entity(); + REQUIRE(e1 == e2); + } } SECTION("component_assigning") { { @@ -355,6 +364,14 @@ TEST_CASE("registry") { REQUIRE_FALSE(ww.find_component(e2)); } } + { + ecs::registry w; + auto e1 = w.create_entity(); + e1.assign_component(1, 2); + e1.assign_component(3, 4); + REQUIRE(e1.get_component().x == 3); + REQUIRE(e1.get_component().y == 4); + } { ecs::registry w; From 58e0df89a765392f21ff9a1293b1e6bba9c4669e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 27 Dec 2018 14:46:11 +0700 Subject: [PATCH 3/4] join process optimization --- ecs.hpp | 162 ++++++++++++++++++++++++++++++++++++-------------- ecs_tests.cpp | 2 +- 2 files changed, 117 insertions(+), 47 deletions(-) diff --git a/ecs.hpp b/ecs.hpp index b5f048e..0b10a62 100644 --- a/ecs.hpp +++ b/ecs.hpp @@ -665,19 +665,43 @@ namespace ecs_hpp template < typename T > const T* find_component_impl_(const entity& ent) const noexcept; - template < typename... Ts, typename F > - void for_joined_components_impl_(F&& f); - template < typename T, typename... Ts, typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs); - template < typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs); + template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > + void for_joined_components_impl_(F&& f, std::index_sequence iseq); + + template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > + void for_joined_components_impl_(F&& f, std::index_sequence iseq) const; + + template < typename T + , typename... Ts + , typename F + , typename S + , typename... Ss + , typename... Cs > + void for_joined_components_impl_( + const entity& e, + const F& f, + detail::component_storage* s, + detail::component_storage*... ss, + Cs&... cs); + + template < typename T + , typename... Ts + , typename F + , typename S + , typename... Ss + , typename... Cs > + void for_joined_components_impl_( + const entity& e, + const F& f, + const detail::component_storage* s, + const detail::component_storage*... ss, + const Cs&... cs) const; - template < typename... Ts, typename F > - void for_joined_components_impl_(F&& f) const; - template < typename T, typename... Ts, typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) const; template < typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) const; + void for_joined_components_impl_(const entity& e, const F& f, Cs&... cs); + + template < typename F, typename... Cs > + void for_joined_components_impl_(const entity& e, const F& f, const Cs&... cs) const; private: entity_id last_entity_id_{0u}; std::vector free_entity_ids_; @@ -931,12 +955,16 @@ namespace ecs_hpp template < typename... Ts, typename F > void registry::for_joined_components(F&& f) { - for_joined_components_impl_(std::forward(f)); + for_joined_components_impl_( + std::forward(f), + std::make_index_sequence()); } template < typename... Ts, typename F > void registry::for_joined_components(F&& f) const { - for_joined_components_impl_(std::forward(f)); + for_joined_components_impl_( + std::forward(f), + std::make_index_sequence()); } template < typename T, typename... Args > @@ -1016,51 +1044,93 @@ namespace ecs_hpp : nullptr; } - template < typename... Ts, typename F > - void registry::for_joined_components_impl_(F&& f) { - for ( const auto id : entity_ids_ ) { - for_joined_components_impl_(entity(*this, id), std::forward(f)); - } + template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > + void registry::for_joined_components_impl_(F&& f, std::index_sequence iseq) { + (void)iseq; + for_each_component([ + this, + f = std::forward(f), + storages = std::make_tuple(find_storage_()...) + ](const entity& e, T& t) mutable { + for_joined_components_impl_( + e, + f, + std::get(storages)..., + t); + }); } - template < typename T, typename... Ts, typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) { - T* c = find_component_impl_(e); + template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > + void registry::for_joined_components_impl_(F&& f, std::index_sequence iseq) const { + (void)iseq; + for_each_component([ + this, + f = std::forward(f), + storages = std::make_tuple(find_storage_()...) + ](const entity& e, const T& t) mutable { + for_joined_components_impl_( + e, + f, + std::get(storages)..., + t); + }); + } + + template < typename T + , typename... Ts + , typename F + , typename S + , typename... Ss + , typename... Cs > + void registry::for_joined_components_impl_( + const entity& e, + const F& f, + detail::component_storage* s, + detail::component_storage*... ss, + Cs&... cs) + { + T* c = s->find(e.id()); if ( c ) { for_joined_components_impl_( e, - std::forward(f), - std::forward(cs)..., + f, + std::forward(ss)..., + cs..., + *c); + } + } + + template < typename T + , typename... Ts + , typename F + , typename S + , typename... Ss + , typename... Cs > + void registry::for_joined_components_impl_( + const entity& e, + const F& f, + const detail::component_storage* s, + const detail::component_storage*... ss, + const Cs&... cs) const + { + const T* c = s->find(e.id()); + if ( c ) { + for_joined_components_impl_( + e, + f, + std::forward(ss)..., + cs..., *c); } } template < typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) { - f(e, std::forward(cs)...); - } - - template < typename... Ts, typename F > - void registry::for_joined_components_impl_(F&& f) const { - for ( const auto id : entity_ids_ ) { - for_joined_components_impl_(entity(const_cast(*this), id), std::forward(f)); - } - } - - template < typename T, typename... Ts, typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) const { - const T* c = find_component_impl_(e); - if ( c ) { - for_joined_components_impl_( - e, - std::forward(f), - std::forward(cs)..., - *c); - } + void registry::for_joined_components_impl_(const entity& e, const F& f, Cs&... cs) { + f(e, cs...); } template < typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, F&& f, Cs&&... cs) const { - f(e, std::forward(cs)...); + void registry::for_joined_components_impl_(const entity& e, const F& f, const Cs&... cs) const { + f(e, cs...); } } diff --git a/ecs_tests.cpp b/ecs_tests.cpp index b3be859..d166053 100644 --- a/ecs_tests.cpp +++ b/ecs_tests.cpp @@ -530,7 +530,7 @@ TEST_CASE("registry") { public: void process(ecs::registry& owner) override { owner.for_joined_components([]( - ecs::entity e, position_c& p, const velocity_c& v) + ecs::entity, position_c& p, const velocity_c& v) { p.x += v.x; p.y += v.y; From 4ad9bc87e1ff795588eceedbd247a4fe96ca51e5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 28 Dec 2018 00:35:21 +0700 Subject: [PATCH 4/4] CI compilation fixes --- ecs.hpp | 174 +++++++++++++++++++++++++++++++++++--------------- ecs_tests.cpp | 38 +++++++++-- 2 files changed, 153 insertions(+), 59 deletions(-) diff --git a/ecs.hpp b/ecs.hpp index 0b10a62..04bafb2 100644 --- a/ecs.hpp +++ b/ecs.hpp @@ -56,10 +56,62 @@ namespace ecs_hpp { namespace detail { + // + // as_const + // + template < typename T > constexpr std::add_const_t& as_const(T& t) noexcept { return t; } + + // + // tuple_tail + // + + namespace impl + { + template < typename T, typename... Ts, std::size_t... Is > + std::tuple tuple_tail_impl(std::tuple&& t, std::index_sequence iseq) { + (void)iseq; + return std::make_tuple(std::move(std::get(t))...); + } + + template < typename T, typename... Ts, std::size_t... Is > + std::tuple tuple_tail_impl(const std::tuple& t, std::index_sequence iseq) { + (void)iseq; + return std::make_tuple(std::get(t)...); + } + } + + template < typename T, typename... Ts > + std::tuple tuple_tail(std::tuple&& t) { + return impl::tuple_tail_impl(std::move(t), std::make_index_sequence()); + } + + template < typename T, typename... Ts > + std::tuple tuple_tail(const std::tuple& t) { + return impl::tuple_tail_impl(t, std::make_index_sequence()); + } + + // + // tuple_contains + // + + template < typename V > + bool tuple_contains(const std::tuple<>& t, const V& v) { + (void)t; + (void)v; + return false; + } + + template < typename V, typename T, typename... Ts > + bool tuple_contains(const std::tuple& t, const V& v) { + if ( std::get<0>(t) == v ) { + return true; + } + return tuple_contains(tuple_tail(t), v); + } } } @@ -674,34 +726,38 @@ namespace ecs_hpp template < typename T , typename... Ts , typename F - , typename S - , typename... Ss + , typename Ss , typename... Cs > void for_joined_components_impl_( const entity& e, const F& f, - detail::component_storage* s, - detail::component_storage*... ss, + const Ss& ss, Cs&... cs); template < typename T , typename... Ts , typename F - , typename S - , typename... Ss + , typename Ss , typename... Cs > void for_joined_components_impl_( const entity& e, const F& f, - const detail::component_storage* s, - const detail::component_storage*... ss, + const Ss& ss, const Cs&... cs) const; template < typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, const F& f, Cs&... cs); + void for_joined_components_impl_( + const entity& e, + const F& f, + const std::tuple<>& ss, + Cs&... cs); template < typename F, typename... Cs > - void for_joined_components_impl_(const entity& e, const F& f, const Cs&... cs) const; + void for_joined_components_impl_( + const entity& e, + const F& f, + const std::tuple<>& ss, + const Cs&... cs) const; private: entity_id last_entity_id_{0u}; std::vector free_entity_ids_; @@ -1044,57 +1100,59 @@ namespace ecs_hpp : nullptr; } - template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > - void registry::for_joined_components_impl_(F&& f, std::index_sequence iseq) { + template < typename T + , typename... Ts + , typename F + , std::size_t I + , std::size_t... Is > + void registry::for_joined_components_impl_( + F&& f, + std::index_sequence iseq) + { (void)iseq; - for_each_component([ - this, - f = std::forward(f), - storages = std::make_tuple(find_storage_()...) - ](const entity& e, T& t) mutable { - for_joined_components_impl_( - e, - f, - std::get(storages)..., - t); - }); - } - - template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is > - void registry::for_joined_components_impl_(F&& f, std::index_sequence iseq) const { - (void)iseq; - for_each_component([ - this, - f = std::forward(f), - storages = std::make_tuple(find_storage_()...) - ](const entity& e, const T& t) mutable { - for_joined_components_impl_( - e, - f, - std::get(storages)..., - t); - }); + const auto ss = std::make_tuple(find_storage_()...); + if ( !detail::tuple_contains(ss, nullptr) ) { + for_each_component([this, &f, &ss](const entity& e, T& t) { + for_joined_components_impl_(e, f, ss, t); + }); + } } template < typename T , typename... Ts , typename F - , typename S - , typename... Ss + , std::size_t I + , std::size_t... Is > + void registry::for_joined_components_impl_( + F&& f, + std::index_sequence iseq) const + { + (void)iseq; + const auto ss = std::make_tuple(find_storage_()...); + if ( !detail::tuple_contains(ss, nullptr) ) { + for_each_component([this, &f, &ss](const entity& e, const T& t) { + detail::as_const(*this).for_joined_components_impl_(e, f, ss, t); + }); + } + } + + template < typename T + , typename... Ts + , typename F + , typename Ss , typename... Cs > void registry::for_joined_components_impl_( const entity& e, const F& f, - detail::component_storage* s, - detail::component_storage*... ss, + const Ss& ss, Cs&... cs) { - T* c = s->find(e.id()); + T* c = std::get<0>(ss)->find(e.id()); if ( c ) { for_joined_components_impl_( e, f, - std::forward(ss)..., + detail::tuple_tail(ss), cs..., *c); } @@ -1103,34 +1161,44 @@ namespace ecs_hpp template < typename T , typename... Ts , typename F - , typename S - , typename... Ss + , typename Ss , typename... Cs > void registry::for_joined_components_impl_( const entity& e, const F& f, - const detail::component_storage* s, - const detail::component_storage*... ss, + const Ss& ss, const Cs&... cs) const { - const T* c = s->find(e.id()); + const T* c = std::get<0>(ss)->find(e.id()); if ( c ) { for_joined_components_impl_( e, f, - std::forward(ss)..., + detail::tuple_tail(ss), cs..., *c); } } template < typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, const F& f, Cs&... cs) { + void registry::for_joined_components_impl_( + const entity& e, + const F& f, + const std::tuple<>& ss, + Cs&... cs) + { + (void)ss; f(e, cs...); } template < typename F, typename... Cs > - void registry::for_joined_components_impl_(const entity& e, const F& f, const Cs&... cs) const { + void registry::for_joined_components_impl_( + const entity& e, + const F& f, + const std::tuple<>& ss, + const Cs&... cs) const + { + (void)ss; f(e, cs...); } } diff --git a/ecs_tests.cpp b/ecs_tests.cpp index d166053..48dfc79 100644 --- a/ecs_tests.cpp +++ b/ecs_tests.cpp @@ -41,14 +41,31 @@ namespace TEST_CASE("detail") { SECTION("get_type_id") { - REQUIRE(ecs::detail::type_family::id() == 1u); - REQUIRE(ecs::detail::type_family::id() == 1u); + using namespace ecs::detail; + REQUIRE(type_family::id() == 1u); + REQUIRE(type_family::id() == 1u); - REQUIRE(ecs::detail::type_family::id() == 2u); - REQUIRE(ecs::detail::type_family::id() == 2u); + REQUIRE(type_family::id() == 2u); + REQUIRE(type_family::id() == 2u); - REQUIRE(ecs::detail::type_family::id() == 1u); - REQUIRE(ecs::detail::type_family::id() == 2u); + REQUIRE(type_family::id() == 1u); + REQUIRE(type_family::id() == 2u); + } + SECTION("tuple_tail") { + using namespace ecs::detail; + { + REQUIRE(tuple_tail(std::make_tuple(1, 2, 3)) == std::make_tuple(2, 3)); + REQUIRE(tuple_tail(std::make_tuple(2, 3)) == std::make_tuple(3)); + REQUIRE(tuple_tail(std::make_tuple(3)) == std::make_tuple()); + } + { + const auto t1 = std::make_tuple(1); + const auto t2 = std::make_tuple(1, 2); + const auto t3 = std::make_tuple(1, 2, 3); + REQUIRE(tuple_tail(t1) == std::make_tuple()); + REQUIRE(tuple_tail(t2) == std::make_tuple(2)); + REQUIRE(tuple_tail(t3) == std::make_tuple(2, 3)); + } } SECTION("sparse_set") { using namespace ecs::detail; @@ -523,6 +540,15 @@ TEST_CASE("registry") { REQUIRE(acc2 == 16); } } + { + ecs::registry w; + auto e1 = w.create_entity(); + e1.assign_component(1, 2); + w.for_joined_components([]( + ecs::entity, const position_c&, const velocity_c&) + { + }); + } } SECTION("systems") { {