* implemented step_proxy * implemented system execution adaptermaster
@@ -4,4 +4,5 @@ | |||||
#include "./ecs/settings.h" | #include "./ecs/settings.h" | ||||
#include "./ecs/signature_list.h" | #include "./ecs/signature_list.h" | ||||
#include "./ecs/signature.h" | #include "./ecs/signature.h" | ||||
#include "./ecs/system_execution_adapter.h" | |||||
#include "./ecs/tag.h" | #include "./ecs/tag.h" |
@@ -65,6 +65,9 @@ struct type_helper | |||||
#define beg_namespace_ecs_core_parallelism ecs_define_namespace_beg(beg_namespace_ecs_core_system, parallelism) | #define beg_namespace_ecs_core_parallelism ecs_define_namespace_beg(beg_namespace_ecs_core_system, parallelism) | ||||
#define end_namespace_ecs_core_parallelism ecs_define_namespace_end(end_namespace_ecs_core_system) | #define end_namespace_ecs_core_parallelism ecs_define_namespace_end(end_namespace_ecs_core_system) | ||||
#define beg_namespace_ecs_core_system_scheduler ecs_define_namespace_beg(beg_namespace_ecs_core_system, scheduler) | |||||
#define end_namespace_ecs_core_system_scheduler ecs_define_namespace_end(end_namespace_ecs_core_system) | |||||
#define beg_namespace_ecs_core_system_storage ecs_define_namespace_beg(beg_namespace_ecs_core_system, storage) | #define beg_namespace_ecs_core_system_storage ecs_define_namespace_beg(beg_namespace_ecs_core_system, storage) | ||||
#define end_namespace_ecs_core_system_storage ecs_define_namespace_end(end_namespace_ecs_core_system) | #define end_namespace_ecs_core_system_storage ecs_define_namespace_end(end_namespace_ecs_core_system) | ||||
@@ -80,6 +83,9 @@ struct type_helper | |||||
#define beg_namespace_ecs_settings_refresh_parallelism ecs_define_namespace_beg(beg_namespace_ecs_settings, refresh_parallelism) | #define beg_namespace_ecs_settings_refresh_parallelism ecs_define_namespace_beg(beg_namespace_ecs_settings, refresh_parallelism) | ||||
#define end_namespace_ecs_settings_refresh_parallelism ecs_define_namespace_end(end_namespace_ecs_settings) | #define end_namespace_ecs_settings_refresh_parallelism ecs_define_namespace_end(end_namespace_ecs_settings) | ||||
#define beg_namespace_ecs_settings_scheduler ecs_define_namespace_beg(beg_namespace_ecs_settings, scheduler) | |||||
#define end_namespace_ecs_settings_scheduler ecs_define_namespace_end(end_namespace_ecs_settings) | |||||
#define beg_namespace_ecs_settings_system_storage ecs_define_namespace_beg(beg_namespace_ecs_settings, system_storage) | #define beg_namespace_ecs_settings_system_storage ecs_define_namespace_beg(beg_namespace_ecs_settings, system_storage) | ||||
#define end_namespace_ecs_settings_system_storage ecs_define_namespace_end(end_namespace_ecs_settings) | #define end_namespace_ecs_settings_system_storage ecs_define_namespace_end(end_namespace_ecs_settings) | ||||
@@ -110,6 +116,9 @@ struct type_helper | |||||
#define beg_namespace_ecs_signature_list_system ecs_define_namespace_beg(beg_namespace_ecs_signature_list, system) | #define beg_namespace_ecs_signature_list_system ecs_define_namespace_beg(beg_namespace_ecs_signature_list, system) | ||||
#define end_namespace_ecs_signature_list_system ecs_define_namespace_end(end_namespace_ecs_signature_list) | #define end_namespace_ecs_signature_list_system ecs_define_namespace_end(end_namespace_ecs_signature_list) | ||||
#define beg_namespace_ecs_system_execution_adapter ecs_define_namespace_beg(beg_namespace_ecs, system_execution_adapter) | |||||
#define end_namespace_ecs_system_execution_adapter ecs_define_namespace_end(end_namespace_ecs) | |||||
#define beg_namespace_ecs_tag ecs_define_namespace_beg(beg_namespace_ecs, tag) | #define beg_namespace_ecs_tag ecs_define_namespace_beg(beg_namespace_ecs, tag) | ||||
#define end_namespace_ecs_tag ecs_define_namespace_end(end_namespace_ecs) | #define end_namespace_ecs_tag ecs_define_namespace_end(end_namespace_ecs) | ||||
@@ -1,3 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "./context/context.h" | |||||
#include "./context/base.h" | |||||
#include "./context/context.h" | |||||
#include "./context/defer_proxy.h" | |||||
#include "./context/step_proxy.h" |
@@ -5,6 +5,12 @@ | |||||
#include <ecs/core/utils/counter_blocker.h> | #include <ecs/core/utils/counter_blocker.h> | ||||
#include <ecs/core/component/manager.h> | #include <ecs/core/component/manager.h> | ||||
#define ecs_context_proxy_func(base, name) \ | |||||
template<typename... T_args> \ | |||||
inline decltype(auto) name(T_args&&... args) \ | |||||
noexcept(noexcept(base::name(std::forward<T_args>(args)...))) \ | |||||
{ return base::name(std::forward<T_args>(args)...); } | |||||
beg_namespace_ecs_context | beg_namespace_ecs_context | ||||
{ | { | ||||
@@ -22,6 +28,7 @@ beg_namespace_ecs_context | |||||
using entity_storage_type = decltype((settings_type { }).entity_storage()(settings_type { }, hana::type_c<chunk_meta_data_type>)); | using entity_storage_type = decltype((settings_type { }).entity_storage()(settings_type { }, hana::type_c<chunk_meta_data_type>)); | ||||
using entity_handle_type = typename entity_storage_type::entity_handle_type; | using entity_handle_type = typename entity_storage_type::entity_handle_type; | ||||
using system_storage_type = decltype((settings_type { }).system_storage()(settings_type { }, hana::type_c<entity_handle_type>)); | using system_storage_type = decltype((settings_type { }).system_storage()(settings_type { }, hana::type_c<entity_handle_type>)); | ||||
using scheduler_type = decltype((settings_type { }).scheduler()(settings_type { })); | |||||
public: | public: | ||||
using handle_type = entity_handle_type; | using handle_type = entity_handle_type; | ||||
@@ -33,6 +40,7 @@ beg_namespace_ecs_context | |||||
component_manager_type _components; | component_manager_type _components; | ||||
entity_storage_type _entities; | entity_storage_type _entities; | ||||
system_storage_type _systems; | system_storage_type _systems; | ||||
scheduler_type _scheduler; | |||||
core::utils::thread_pool _thread_pool; | core::utils::thread_pool _thread_pool; | ||||
@@ -42,21 +50,22 @@ beg_namespace_ecs_context | |||||
public: | public: | ||||
inline base_t() | inline base_t() | ||||
: _components () | : _components () | ||||
, _entities (settings_type { }.entity_storage()(settings_type { }, hana::type_c<chunk_meta_data_type>)) | |||||
, _systems (settings_type { }.system_storage()(settings_type { }, hana::type_c<entity_handle_type>)) | |||||
, _entities ((settings_type { }).entity_storage()(settings_type { }, hana::type_c<chunk_meta_data_type>)) | |||||
, _systems ((settings_type { }).system_storage()(settings_type { }, hana::type_c<entity_handle_type>)) | |||||
, _scheduler ((settings_type { }).scheduler()(settings_type { })) | |||||
, _thread_pool (std::thread::hardware_concurrency() != 0 | , _thread_pool (std::thread::hardware_concurrency() != 0 | ||||
? std::thread::hardware_concurrency() | ? std::thread::hardware_concurrency() | ||||
: 8 ) | : 8 ) | ||||
{ } | { } | ||||
public: /* misc */ | |||||
protected: /* misc */ | |||||
template<typename T_func> | template<typename T_func> | ||||
inline decltype(auto) post_in_thread_pool(T_func&& func) | inline decltype(auto) post_in_thread_pool(T_func&& func) | ||||
{ | { | ||||
return _thread_pool.post(std::forward<T_func>(func)); | return _thread_pool.post(std::forward<T_func>(func)); | ||||
} | } | ||||
public: /* entity */ | |||||
protected: /* entity */ | |||||
template<typename... T_args> | template<typename... T_args> | ||||
inline handle_type create_entity(T_args&&... args) | inline handle_type create_entity(T_args&&... args) | ||||
{ | { | ||||
@@ -74,7 +83,7 @@ beg_namespace_ecs_context | |||||
return _entities.is_valid(handle); | return _entities.is_valid(handle); | ||||
} | } | ||||
public: /* component */ | |||||
protected: /* component */ | |||||
template<typename T_component_tag> | template<typename T_component_tag> | ||||
inline decltype(auto) add_component(const handle_type& handle, T_component_tag ct) | inline decltype(auto) add_component(const handle_type& handle, T_component_tag ct) | ||||
{ | { | ||||
@@ -115,7 +124,13 @@ beg_namespace_ecs_context | |||||
bitset.set_component(ct, false); | bitset.set_component(ct, false); | ||||
} | } | ||||
public: /* systems */ | |||||
protected: /* systems */ | |||||
template<typename T_system_tag> | |||||
inline auto& system(T_system_tag st) | |||||
{ | |||||
return _systems.instance_by_tag(st).system(); | |||||
} | |||||
template<typename T_func> | template<typename T_func> | ||||
inline void for_systems_sequential(T_func&& func) | inline void for_systems_sequential(T_func&& func) | ||||
{ | { | ||||
@@ -150,6 +165,28 @@ beg_namespace_ecs_context | |||||
_(this)->for_systems_sequential(func); | _(this)->for_systems_sequential(func); | ||||
}); | }); | ||||
} | } | ||||
private: | |||||
template<typename... T_system_tags> | |||||
static constexpr decltype(auto) make_system_tag_list(T_system_tags&&... tags) noexcept | |||||
{ | |||||
auto list = core::mp::list::make(std::forward<T_system_tags>(tags)...); | |||||
return hana::if_( | |||||
hana::equal(hana::size(list), hana::size_c<0>), | |||||
(settings_type { }).system_signatures().tags(), | |||||
list); | |||||
} | |||||
protected: /* execute */ | |||||
template<typename... T_system_tags> | |||||
inline decltype(auto) execute_systems(T_system_tags&&... sts) noexcept | |||||
{ | |||||
auto tags = make_system_tag_list(std::forward<T_system_tags>(sts)...); | |||||
return [tags, this](auto&&... fns) { | |||||
auto os = hana::overload_linearly(std::forward<decltype(fns)>(fns)...); | |||||
this->_scheduler.execute(*this, tags, os); | |||||
}; | |||||
} | |||||
}; | }; | ||||
} | } | ||||
@@ -3,7 +3,7 @@ | |||||
#include <ecs/config.h> | #include <ecs/config.h> | ||||
#include <ecs/core/utils/scope_guard.h> | #include <ecs/core/utils/scope_guard.h> | ||||
#include "./base.h" | |||||
#include "./step_proxy.h" | |||||
beg_namespace_ecs_context | beg_namespace_ecs_context | ||||
{ | { | ||||
@@ -12,8 +12,12 @@ beg_namespace_ecs_context | |||||
{ | { | ||||
template<typename T_settings> | template<typename T_settings> | ||||
struct context_t | struct context_t | ||||
: public base_t<T_settings> | |||||
: public step_proxy_t<T_settings> | |||||
{ | { | ||||
private: | |||||
using settings_type = T_settings; | |||||
using step_proxy_type = step_proxy_t<settings_type>; | |||||
private: | private: | ||||
void refresh() | void refresh() | ||||
{ | { | ||||
@@ -22,11 +26,13 @@ beg_namespace_ecs_context | |||||
public: | public: | ||||
template<typename T_step_func> | template<typename T_step_func> | ||||
inline decltype(auto) step(T_step_func&& set_func) | |||||
inline decltype(auto) step(T_step_func&& step_func) | |||||
{ | { | ||||
ecs_make_scope_guard([this]{ | ecs_make_scope_guard([this]{ | ||||
this->refresh(); | this->refresh(); | ||||
}); | }); | ||||
std::forward<T_step_func>(step_func)(static_cast<step_proxy_type&>(*this)); | |||||
} | } | ||||
}; | }; | ||||
@@ -0,0 +1,36 @@ | |||||
#pragma once | |||||
#include <ecs/config.h> | |||||
#include "./base.h" | |||||
beg_namespace_ecs_context | |||||
{ | |||||
namespace __impl | |||||
{ | |||||
template<typename T_settings> | |||||
struct defer_proxy_t | |||||
: public base_t<T_settings> | |||||
{ | |||||
private: | |||||
using base_type = base_t<T_settings>; | |||||
public: /* entity */ | |||||
ecs_context_proxy_func(base_type, create_entity) | |||||
ecs_context_proxy_func(base_type, kill_entity) | |||||
ecs_context_proxy_func(base_type, is_alive) | |||||
public: /* component */ | |||||
ecs_context_proxy_func(base_type, add_component) | |||||
ecs_context_proxy_func(base_type, has_component) | |||||
ecs_context_proxy_func(base_type, get_component) | |||||
ecs_context_proxy_func(base_type, remove_component) | |||||
public: /* system */ | |||||
ecs_context_proxy_func(base_type, system) | |||||
}; | |||||
} | |||||
} | |||||
end_namespace_ecs_context |
@@ -0,0 +1,25 @@ | |||||
#pragma once | |||||
#include <ecs/config.h> | |||||
#include "./defer_proxy.h" | |||||
beg_namespace_ecs_context | |||||
{ | |||||
namespace __impl | |||||
{ | |||||
template<typename T_settings> | |||||
struct step_proxy_t | |||||
: public defer_proxy_t<T_settings> | |||||
{ | |||||
private: | |||||
using base_type = defer_proxy_t<T_settings>; | |||||
public: /* execute */ | |||||
ecs_context_proxy_func(base_type, execute_systems) | |||||
}; | |||||
} | |||||
} | |||||
end_namespace_ecs_context |
@@ -2,4 +2,5 @@ | |||||
#include "./system/instance.h" | #include "./system/instance.h" | ||||
#include "./system/parallelism.h" | #include "./system/parallelism.h" | ||||
#include "./system/scheduler.h" | |||||
#include "./system/storage.h" | #include "./system/storage.h" |
@@ -0,0 +1,3 @@ | |||||
#pragma once | |||||
#include "./scheduler/atomic_counter.h" |
@@ -0,0 +1,21 @@ | |||||
#pragma once | |||||
#include <ecs/config.h> | |||||
beg_namespace_ecs_core_system_scheduler | |||||
{ | |||||
template<typename T_settings> | |||||
struct atomic_counter | |||||
{ | |||||
public: | |||||
using settings_type = T_settings; | |||||
public: | |||||
template<typename... T_args> | |||||
inline void execute(T_args&&...) | |||||
{ } | |||||
}; | |||||
} | |||||
end_namespace_ecs_core_system_scheduler |
@@ -0,0 +1,3 @@ | |||||
#pragma once | |||||
#include "./scheduler/atomic_counter.h" |
@@ -0,0 +1,22 @@ | |||||
#pragma once | |||||
#include <ecs/config.h> | |||||
#include <ecs/core/system/scheduler/atomic_counter.h> | |||||
beg_namespace_ecs_settings_scheduler | |||||
{ | |||||
namespace __impl | |||||
{ | |||||
struct atomic_counter_t | |||||
{ | |||||
template<typename T_settings> | |||||
constexpr decltype(auto) operator()(T_settings) const noexcept | |||||
{ return core::system::scheduler::atomic_counter<T_settings> { }; } | |||||
}; | |||||
} | |||||
constexpr decltype(auto) atomic_counter = __impl::atomic_counter_t { }; | |||||
} | |||||
end_namespace_ecs_settings_scheduler |
@@ -7,6 +7,7 @@ | |||||
#include "./system_storage.h" | #include "./system_storage.h" | ||||
#include "./entity_storage.h" | #include "./entity_storage.h" | ||||
#include "./refresh_parallelism.h" | #include "./refresh_parallelism.h" | ||||
#include "./scheduler.h" | |||||
beg_namespace_ecs_settings | beg_namespace_ecs_settings | ||||
{ | { | ||||
@@ -18,6 +19,7 @@ beg_namespace_ecs_settings | |||||
constexpr decltype(auto) system_storage = hana::size_c<2>; | constexpr decltype(auto) system_storage = hana::size_c<2>; | ||||
constexpr decltype(auto) entity_storage = hana::size_c<3>; | constexpr decltype(auto) entity_storage = hana::size_c<3>; | ||||
constexpr decltype(auto) refresh_parallelism = hana::size_c<4>; | constexpr decltype(auto) refresh_parallelism = hana::size_c<4>; | ||||
constexpr decltype(auto) scheduler = hana::size_c<5>; | |||||
} | } | ||||
namespace __impl | namespace __impl | ||||
@@ -53,6 +55,9 @@ beg_namespace_ecs_settings | |||||
constexpr decltype(auto) refresh_parallelism() const noexcept | constexpr decltype(auto) refresh_parallelism() const noexcept | ||||
{ return get(keys::refresh_parallelism); } | { return get(keys::refresh_parallelism); } | ||||
constexpr decltype(auto) scheduler() const noexcept | |||||
{ return get(keys::scheduler); } | |||||
public: /* setter */ | public: /* setter */ | ||||
template<typename T> | template<typename T> | ||||
constexpr decltype(auto) component_signatures(T t) const noexcept | constexpr decltype(auto) component_signatures(T t) const noexcept | ||||
@@ -73,6 +78,10 @@ beg_namespace_ecs_settings | |||||
template<typename T> | template<typename T> | ||||
constexpr decltype(auto) refresh_parallelism(T t) const noexcept | constexpr decltype(auto) refresh_parallelism(T t) const noexcept | ||||
{ return change(keys::refresh_parallelism, t); } | { return change(keys::refresh_parallelism, t); } | ||||
template<typename T> | |||||
constexpr decltype(auto) scheduler(T t) const noexcept | |||||
{ return change(keys::scheduler, t); } | |||||
}; | }; | ||||
struct make_t | struct make_t | ||||
@@ -85,7 +94,8 @@ beg_namespace_ecs_settings | |||||
.add(keys::system_signatures, list::empty) | .add(keys::system_signatures, list::empty) | ||||
.add(keys::system_storage, system_storage::tuple) | .add(keys::system_storage, system_storage::tuple) | ||||
.add(keys::entity_storage, entity_storage::dynamic<1024>) | .add(keys::entity_storage, entity_storage::dynamic<1024>) | ||||
.add(keys::refresh_parallelism, refresh_parallelism::enable); | |||||
.add(keys::refresh_parallelism, refresh_parallelism::enable) | |||||
.add(keys::scheduler, scheduler::atomic_counter); | |||||
return settings_t<decay_t<decltype(options)>> { }; | return settings_t<decay_t<decltype(options)>> { }; | ||||
} | } | ||||
}; | }; | ||||
@@ -20,6 +20,15 @@ beg_namespace_ecs_signature_list_system | |||||
{ return hana::size(items); } | { return hana::size(items); } | ||||
public: /* get */ | public: /* get */ | ||||
constexpr decltype(auto) tags() const noexcept | |||||
{ | |||||
return hana::unpack( | |||||
hana::transform(items, [](auto& ssig){ | |||||
return core::mp::unwrap(ssig).tag(); | |||||
}), | |||||
core::mp::list::make); | |||||
} | |||||
template<typename T_system_tag> | template<typename T_system_tag> | ||||
constexpr decltype(auto) get_by_tag(T_system_tag st) const noexcept | constexpr decltype(auto) get_by_tag(T_system_tag st) const noexcept | ||||
{ | { | ||||
@@ -0,0 +1,77 @@ | |||||
#pragma once | |||||
#include <ecs/config.h> | |||||
beg_namespace_ecs_system_execution_adapter | |||||
{ | |||||
namespace __impl | |||||
{ | |||||
template<typename T_predicate> | |||||
struct predicate_holder | |||||
{ | |||||
private: | |||||
using predicate_type = T_predicate; | |||||
template<typename T_instance> | |||||
using predicate_result_type = decltype( | |||||
std::declval<predicate_type>()( | |||||
std::declval<core::mp::decay_t<T_instance>>().system())); | |||||
template<typename T_predicate_result> | |||||
using enabler = std::enable_if_t<T_predicate_result { }, void>; | |||||
public: | |||||
template<typename T_func> | |||||
constexpr decltype(auto) detailed_instance(T_func&& func) noexcept | |||||
{ | |||||
return [f = std::forward<T_func>(func)](auto& instance, auto& executor) | |||||
-> enabler<predicate_result_type<decltype(instance)>> | |||||
{ | |||||
f(instance, executor); | |||||
}; | |||||
} | |||||
template<typename T_func> | |||||
constexpr decltype(auto) detailed(T_func&& func) noexcept | |||||
{ | |||||
return detailed_instance([f = std::forward<T_func>(func)](auto& instance, auto& executor) { | |||||
f(instance.system(), executor); | |||||
}); | |||||
} | |||||
template<typename T_func> | |||||
constexpr decltype(auto) for_subtasks(T_func&& func) noexcept | |||||
{ | |||||
return detailed([f = std::forward<T_func>(func)](auto& system, auto& executor){ | |||||
executor.for_subtasks([&system, &f](auto& data){ | |||||
f(system, data); | |||||
}); | |||||
}); | |||||
} | |||||
}; | |||||
} | |||||
template<typename T_func> | |||||
constexpr decltype(auto) matching(T_func) noexcept | |||||
{ | |||||
return __impl::predicate_holder<T_func> { }; | |||||
} | |||||
constexpr decltype(auto) all() noexcept | |||||
{ | |||||
return matching(hana::always(hana::true_c)); | |||||
} | |||||
template<typename... T_system_tags> | |||||
constexpr decltype(auto) tags(T_system_tags... tags) noexcept | |||||
{ | |||||
auto tag_set = hana::make_set(tags...); | |||||
return matching([tag_set](auto& system) { | |||||
auto tag = tag::system::make(system); | |||||
return hana::contains(tag_set, tag); | |||||
}); | |||||
} | |||||
} | |||||
end_namespace_ecs_system_execution_adapter |
@@ -111,16 +111,21 @@ constexpr decltype(auto) settings = ::ecs::settings::make() | |||||
.component_signatures(cs_list) | .component_signatures(cs_list) | ||||
.system_signatures (ss_list); | .system_signatures (ss_list); | ||||
namespace sea = ::ecs::system_execution_adapter; | |||||
TEST(DummyTest, fuu) | TEST(DummyTest, fuu) | ||||
{ | { | ||||
std::mutex m; | |||||
auto context = ::ecs::context::make(settings); | auto context = ::ecs::context::make(settings); | ||||
context.for_systems_dispatch([&m](auto& instance){ | |||||
std::lock_guard l(m); | |||||
std::cout | |||||
<< std::this_thread::get_id() | |||||
<< " " | |||||
<< type_helper<decltype(instance.system())>::name() | |||||
<< std::endl; | |||||
context.step([](auto& step_proxy){ | |||||
step_proxy.execute_systems()( | |||||
sea::tags(st::accelerate) | |||||
.for_subtasks([](auto& s, auto& data){ | |||||
std::cout << "accelerate" << std::endl; | |||||
}), | |||||
sea::tags(st::move) | |||||
.for_subtasks([](auto& s, auto& data){ | |||||
std::cout << "move" << std::endl; | |||||
}) | |||||
); | |||||
}); | }); | ||||
} | } |