* implemented step_proxy * implemented system execution adaptermaster
@@ -4,4 +4,5 @@ | |||
#include "./ecs/settings.h" | |||
#include "./ecs/signature_list.h" | |||
#include "./ecs/signature.h" | |||
#include "./ecs/system_execution_adapter.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 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 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 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 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 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 end_namespace_ecs_tag ecs_define_namespace_end(end_namespace_ecs) | |||
@@ -1,3 +1,6 @@ | |||
#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/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 | |||
{ | |||
@@ -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_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 scheduler_type = decltype((settings_type { }).scheduler()(settings_type { })); | |||
public: | |||
using handle_type = entity_handle_type; | |||
@@ -33,6 +40,7 @@ beg_namespace_ecs_context | |||
component_manager_type _components; | |||
entity_storage_type _entities; | |||
system_storage_type _systems; | |||
scheduler_type _scheduler; | |||
core::utils::thread_pool _thread_pool; | |||
@@ -42,21 +50,22 @@ beg_namespace_ecs_context | |||
public: | |||
inline base_t() | |||
: _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 | |||
? std::thread::hardware_concurrency() | |||
: 8 ) | |||
{ } | |||
public: /* misc */ | |||
protected: /* misc */ | |||
template<typename T_func> | |||
inline decltype(auto) post_in_thread_pool(T_func&& func) | |||
{ | |||
return _thread_pool.post(std::forward<T_func>(func)); | |||
} | |||
public: /* entity */ | |||
protected: /* entity */ | |||
template<typename... T_args> | |||
inline handle_type create_entity(T_args&&... args) | |||
{ | |||
@@ -74,7 +83,7 @@ beg_namespace_ecs_context | |||
return _entities.is_valid(handle); | |||
} | |||
public: /* component */ | |||
protected: /* component */ | |||
template<typename T_component_tag> | |||
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); | |||
} | |||
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> | |||
inline void for_systems_sequential(T_func&& func) | |||
{ | |||
@@ -150,6 +165,28 @@ beg_namespace_ecs_context | |||
_(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/core/utils/scope_guard.h> | |||
#include "./base.h" | |||
#include "./step_proxy.h" | |||
beg_namespace_ecs_context | |||
{ | |||
@@ -12,8 +12,12 @@ beg_namespace_ecs_context | |||
{ | |||
template<typename T_settings> | |||
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: | |||
void refresh() | |||
{ | |||
@@ -22,11 +26,13 @@ beg_namespace_ecs_context | |||
public: | |||
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]{ | |||
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/parallelism.h" | |||
#include "./system/scheduler.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 "./entity_storage.h" | |||
#include "./refresh_parallelism.h" | |||
#include "./scheduler.h" | |||
beg_namespace_ecs_settings | |||
{ | |||
@@ -18,6 +19,7 @@ beg_namespace_ecs_settings | |||
constexpr decltype(auto) system_storage = hana::size_c<2>; | |||
constexpr decltype(auto) entity_storage = hana::size_c<3>; | |||
constexpr decltype(auto) refresh_parallelism = hana::size_c<4>; | |||
constexpr decltype(auto) scheduler = hana::size_c<5>; | |||
} | |||
namespace __impl | |||
@@ -53,6 +55,9 @@ beg_namespace_ecs_settings | |||
constexpr decltype(auto) refresh_parallelism() const noexcept | |||
{ return get(keys::refresh_parallelism); } | |||
constexpr decltype(auto) scheduler() const noexcept | |||
{ return get(keys::scheduler); } | |||
public: /* setter */ | |||
template<typename T> | |||
constexpr decltype(auto) component_signatures(T t) const noexcept | |||
@@ -73,6 +78,10 @@ beg_namespace_ecs_settings | |||
template<typename T> | |||
constexpr decltype(auto) refresh_parallelism(T t) const noexcept | |||
{ 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 | |||
@@ -85,7 +94,8 @@ beg_namespace_ecs_settings | |||
.add(keys::system_signatures, list::empty) | |||
.add(keys::system_storage, system_storage::tuple) | |||
.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)>> { }; | |||
} | |||
}; | |||
@@ -20,6 +20,15 @@ beg_namespace_ecs_signature_list_system | |||
{ return hana::size(items); } | |||
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> | |||
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) | |||
.system_signatures (ss_list); | |||
namespace sea = ::ecs::system_execution_adapter; | |||
TEST(DummyTest, fuu) | |||
{ | |||
std::mutex m; | |||
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; | |||
}) | |||
); | |||
}); | |||
} |