|
- #pragma once
-
- #include <ecs/config.h>
- #include <ecs/core/utils/thread_pool.h>
- #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
- {
-
- namespace __impl
- {
- template<typename T_settings>
- struct base_t
- {
- public:
- using settings_type = T_settings;
-
- protected:
- using component_manager_type = core::component::manager<settings_type>;
- using chunk_meta_data_type = typename component_manager_type::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 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;
-
- private:
- using handle_vector_type = std::vector<handle_type>;
-
- protected:
- component_manager_type _components;
- entity_storage_type _entities;
- system_storage_type _systems;
- scheduler_type _scheduler;
-
- core::utils::thread_pool _thread_pool;
-
- handle_vector_type _to_match;
- handle_vector_type _to_kill;
-
- 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>))
- , _scheduler ((settings_type { }).scheduler()(settings_type { }))
- , _thread_pool (std::thread::hardware_concurrency() != 0
- ? std::thread::hardware_concurrency()
- : 8 )
- { }
-
- 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));
- }
-
- protected: /* entity */
- template<typename... T_args>
- inline handle_type create_entity(T_args&&... args)
- {
- _to_match.emplace_back(_entities.claim(std::forward<T_args>(args)...));
- return _to_match.back();
- }
-
- inline void kill_entity(const handle_type& handle)
- {
- _to_kill.emplace_back(handle);
- }
-
- inline bool is_alive(const handle_type& handle) const
- {
- return _entities.is_valid(handle);
- }
-
- protected: /* component */
- template<typename T_component_tag>
- inline decltype(auto) add_component(const handle_type& handle, T_component_tag ct)
- {
- _to_match.emplace_back(handle);
- auto& meta = _entities.meta_data(handle);
- auto& cmd = meta.chunk_meta_data();
- auto& c = _components.add(ct, handle, cmd);
- auto& bitset = meta.bitset();
- bitset.set_component(ct, true);
- return c;
- }
-
- template<typename T_component_tag>
- inline decltype(auto) has_component(const handle_type& handle, T_component_tag ct)
- {
- auto& meta = _entities.meta_data(handle);
- auto& bitset = meta.bitset();
- return bitset.has_component(ct);
- }
-
- template<typename T_component_tag>
- inline decltype(auto) get_component(const handle_type& handle, T_component_tag ct)
- {
- auto& meta = _entities.meta_data(handle);
- auto& bitset = meta.bitset();
- auto& cmd = meta.chunk_meta_data();
- if (!bitset.has_component(ct))
- throw std::invalid_argument("entity does not contain the requested compnent");
- return _components.get(ct, handle, cmd);
- }
-
- template<typename T_component_tag>
- inline decltype(auto) remove_component(const handle_type& handle, T_component_tag ct)
- {
- _to_match.emplace_back(handle);
- auto& meta = _entities.meta_data(handle);
- auto& bitset = meta.bitset();
- bitset.set_component(ct, false);
- }
-
- 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)
- {
- _systems.for_each(std::forward<T_func>(func));
- }
-
- template<typename T_func>
- inline void for_systems_parallel(T_func&& func)
- {
- core::utils::counter_blocker counter(_systems.size());
- counter.execute_and_wait_until_zero([this, &counter, func = std::forward<T_func>(func)]{
- _systems.for_each([this, &counter, &func](auto& instance){
- this->post_in_thread_pool([&counter, &func, &instance]{
- ecs_make_scope_guard([&counter](){
- counter.decrement_and_notify_one();
- });
- func(instance);
- });
- });
- });
- }
-
- template<typename T_func>
- inline void for_systems_dispatch(T_func&& func)
- {
- hana::eval_if(
- (settings_type { }).refresh_parallelism(),
- [this, func=std::forward<T_func>(func)](auto _) {
- _(this)->for_systems_parallel(func);
- },
- [this, func=std::forward<T_func>(func)](auto _) {
- _(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);
- };
- }
- };
- }
-
- }
- end_namespace_ecs_context
|