@@ -135,7 +135,7 @@ beg_namespace_ecs_core_entity_storage | |||||
auto index = handle.index(); | auto index = handle.index(); | ||||
return _container.at(index); | return _container.at(index); | ||||
} | } | ||||
}; | }; | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "./system/instance.h" | #include "./system/instance.h" | ||||
#include "./system/parallelism.h" | |||||
#include "./system/storage.h" | #include "./system/storage.h" |
@@ -3,37 +3,198 @@ | |||||
#include <ecs/config.h> | #include <ecs/config.h> | ||||
#include <ecs/signature/system.h> | #include <ecs/signature/system.h> | ||||
#include <ecs/core/utils/bitset.h> | #include <ecs/core/utils/bitset.h> | ||||
#include <ecs/core/utils/fixed_function.h> | |||||
beg_namespace_ecs_core_system | beg_namespace_ecs_core_system | ||||
{ | { | ||||
template<typename T_settings> | |||||
struct deferred_function_vector | |||||
{ | |||||
private: | |||||
using deferred_proxy_type = int; | |||||
using function_type = utils::fixed_function<void(deferred_proxy_type&)>; | |||||
using function_vector_type = std::vector<function_type>; | |||||
private: | |||||
function_vector_type _functions; | |||||
public: | |||||
inline void clear() noexcept | |||||
{ _functions.clear(); } | |||||
template<typename T_func> | |||||
inline void add(T_func&& func) | |||||
{ _functions.emplace_back(std::forward<T_func>(func)); } | |||||
template<typename T_proxy> | |||||
inline void execute_all(T_proxy& proxy) const | |||||
{ | |||||
for (auto& f : _functions) | |||||
{ | |||||
f(proxy); | |||||
} | |||||
} | |||||
}; | |||||
template<typename T_settings, typename T_system_signature, typename T_entity_handle> | template<typename T_settings, typename T_system_signature, typename T_entity_handle> | ||||
struct instance | struct instance | ||||
{ | { | ||||
static_assert(decltype(signature::system::is_valid(mp::unwrap_t<T_system_signature> { })) { }); | static_assert(decltype(signature::system::is_valid(mp::unwrap_t<T_system_signature> { })) { }); | ||||
public: | public: | ||||
using settings_type = T_settings; | |||||
using system_signature_type = T_system_signature; | |||||
using this_type = instance<settings_type, system_signature_type, T_entity_handle>; | |||||
using system_tag_type = mp::decay_t<decltype(core::mp::unwrap(system_signature_type { }).tag())>; | |||||
using system_type = mp::unwrap_t<system_tag_type>; | |||||
using settings_type = T_settings; | |||||
using system_signature_type = T_system_signature; | |||||
using this_type = instance<settings_type, system_signature_type, T_entity_handle>; | |||||
using system_tag_type = mp::decay_t<decltype(core::mp::unwrap(system_signature_type { }).tag())>; | |||||
using system_type = mp::unwrap_t<system_tag_type>; | |||||
using output_type = mp::unwrap_t<mp::decay_t<decltype(mp::unwrap(system_signature_type { }).output())>>; | |||||
private: | private: | ||||
using bitset_type = utils::bitset<settings_type>; | |||||
using entity_handle_type = T_entity_handle; | |||||
using signature_list_type = decltype((settings_type { }).system_signatures()); | |||||
using bitset_type = utils::bitset<settings_type>; | |||||
using entity_handle_type = T_entity_handle; | |||||
using executor_type = decltype(mp::unwrap(system_signature_type { }).parallelism()()); | |||||
using entity_handle_set_type = std::set<entity_handle_type>; | |||||
struct state | |||||
: public output_type | |||||
{ | |||||
private: | |||||
using deferred_function_type = deferred_function_vector<settings_type>; | |||||
using entity_handles_type = std::vector<entity_handle_type>; | |||||
public: | |||||
deferred_function_type deferred_functions; | |||||
entity_handles_type to_kill; | |||||
public: | |||||
inline void clear() | |||||
{ | |||||
deferred_functions.clear(); | |||||
to_kill.clear(); | |||||
} | |||||
inline decltype(auto) as_output() | |||||
{ return static_cast<output_type&>(*this); } | |||||
}; | |||||
using state_vector = std::vector<state>; | |||||
private: | private: | ||||
bitset_type _bitset; | |||||
system_type _system; | |||||
std::set<entity_handle_type> _subscribed; | |||||
bitset_type _bitset; | |||||
system_type _system; | |||||
executor_type _executor; | |||||
entity_handle_set_type _subscribed; | |||||
state_vector _states; | |||||
public: | public: | ||||
instance() | |||||
: _bitset () | |||||
, _system () | |||||
, _executor (mp::unwrap(system_signature_type { }).parallelism()()) | |||||
, _subscribed() | |||||
, _states () | |||||
{ } | |||||
instance(const instance&) = delete; | |||||
instance& operator=(const instance&) = delete; | |||||
instance(instance&&) = default; | |||||
instance& operator=(instance&&) = default; | |||||
private: | |||||
inline void clear_and_prepare(size_t size) | |||||
{ | |||||
_states.resize(size); | |||||
for (auto& state : _states) | |||||
{ | |||||
state.clear(); | |||||
} | |||||
} | |||||
public: | |||||
template<typename T_context, typename T_func> | |||||
inline void prepare_and_wait_subtasks(T_context& context, size_t n, T_func& func) | |||||
{ | |||||
assert(n > 0); | |||||
clear_and_prepare(n); | |||||
utils::counter_blocker b(n-1); | |||||
auto run_in_seperate_thread = [this, &context, &b](auto& f) { | |||||
return [this, &b, &context, &f](auto&&... xs) { | |||||
context.post_in_thread_pool([&f, &b, xs...]() { | |||||
ecs_make_scope_guard([&b](){ | |||||
b.decrement_and_notify_one(); | |||||
}); | |||||
f(xs...); | |||||
}); | |||||
}; | |||||
}; | |||||
b.execute_and_wait_until_zero([&func, &run_in_seperate_thread]{ | |||||
func(run_in_seperate_thread); | |||||
}); | |||||
} | |||||
public: /* bitset */ | |||||
inline const auto& bitset() const noexcept | |||||
{ return _bitset; } | |||||
public: /* system */ | |||||
inline auto& system() noexcept | inline auto& system() noexcept | ||||
{ return _system; } | { return _system; } | ||||
inline const auto& system() const noexcept | inline const auto& system() const noexcept | ||||
{ return _system; } | { return _system; } | ||||
constexpr decltype(auto) system_id() const noexcept | |||||
{ return (signature_list_type { }).template id_by_type<system_type>(); } | |||||
public: /* subscribed */ | |||||
inline auto subscribed_count() const noexcept | |||||
{ return _subscribed.size(); } | |||||
inline auto& subscribed() noexcept | |||||
{ return _subscribed; } | |||||
inline bool is_subscribed(const entity_handle_type& handle) const | |||||
{ return (_subscribed.find(handle) != _subscribed.end()); } | |||||
inline void subscribe(const entity_handle_type& handle) | |||||
{ _subscribed.emplace(handle); } | |||||
inline void unsubscribe(const entity_handle_type& handle) | |||||
{ _subscribed.erase(handle); } | |||||
public: /* states */ | |||||
template<typename T_func> | |||||
inline void for_states(T_func&& func) | |||||
{ | |||||
for (auto& state : _states) | |||||
{ | |||||
func(state); | |||||
} | |||||
} | |||||
template<typename T_func> | |||||
inline void for_outputs(T_func&& func) | |||||
{ | |||||
for (auto& state : _states) | |||||
{ | |||||
func(state.as_output()); | |||||
} | |||||
} | |||||
template<typename T_proxy> | |||||
inline void execute_deferred_functions(T_proxy& proxy) | |||||
{ | |||||
for (auto& state : _states) | |||||
{ | |||||
state.deferred_functions.execute_all(proxy); | |||||
} | |||||
} | |||||
}; | }; | ||||
} | } |
@@ -0,0 +1,4 @@ | |||||
#pragma once | |||||
#include "./parallelism/composer.h" | |||||
#include "./parallelism/strategy.h" |
@@ -6,7 +6,7 @@ beg_namespace_ecs_core_parallelism | |||||
{ | { | ||||
template<typename T_parameters> | template<typename T_parameters> | ||||
struct fixed_threshold | |||||
struct fixed_threshold | |||||
{ | { | ||||
using parameters_type = T_parameters; | using parameters_type = T_parameters; | ||||
using strategy_lower_type = typename parameters_type::strategy_lower_type; | using strategy_lower_type = typename parameters_type::strategy_lower_type; | ||||
@@ -5,7 +5,7 @@ | |||||
beg_namespace_ecs_core_parallelism | beg_namespace_ecs_core_parallelism | ||||
{ | { | ||||
struct none | |||||
struct none | |||||
{ | { | ||||
template<typename T_instance, typename T_context, typename T_func> | template<typename T_instance, typename T_context, typename T_func> | ||||
inline void operator()(T_instance& instance, T_context& context, T_func&& func) const | inline void operator()(T_instance& instance, T_context& context, T_func&& func) const | ||||
@@ -6,7 +6,7 @@ beg_namespace_ecs_core_parallelism | |||||
{ | { | ||||
template<typename T_parameters> | template<typename T_parameters> | ||||
struct split_evenly | |||||
struct split_evenly | |||||
{ | { | ||||
using parameters_type = T_parameters; | using parameters_type = T_parameters; | ||||
@@ -14,7 +14,7 @@ beg_namespace_ecs_core_parallelism | |||||
inline void operator()(T_context& context, T_instance& instance, T_func&& func) const | inline void operator()(T_context& context, T_instance& instance, T_func&& func) const | ||||
{ | { | ||||
// auto split_count = parameters_type::get_split_count(); | // auto split_count = parameters_type::get_split_count(); | ||||
// TODO | |||||
// TODO | |||||
} | } | ||||
}; | }; | ||||
@@ -14,7 +14,7 @@ beg_namespace_ecs_core_utils | |||||
static constexpr decltype(auto) csl() noexcept | static constexpr decltype(auto) csl() noexcept | ||||
{ return (T_settings { }).component_signatures(); } | { return (T_settings { }).component_signatures(); } | ||||
static constexpr decltype(auto) all_components() noexcept | |||||
static constexpr decltype(auto) all_components() noexcept | |||||
{ return csl().all_components(); } | { return csl().all_components(); } | ||||
public: | public: | ||||
@@ -25,7 +25,7 @@ beg_namespace_ecs_signature_system_parallelism | |||||
{ return ::ecs::core::system::parallelism::fixed_threshold<parameters> { }; } | { return ::ecs::core::system::parallelism::fixed_threshold<parameters> { }; } | ||||
}; | }; | ||||
struct fixed_threshold_t | |||||
struct fixed_threshold_t | |||||
{ | { | ||||
template<typename T_threshold, typename T_lower_strategy, typename T_greater_strategy> | template<typename T_threshold, typename T_lower_strategy, typename T_greater_strategy> | ||||
constexpr decltype(auto) operator()(T_threshold, T_lower_strategy, T_greater_strategy) const noexcept | constexpr decltype(auto) operator()(T_threshold, T_lower_strategy, T_greater_strategy) const noexcept | ||||
@@ -13,7 +13,7 @@ beg_namespace_ecs_signature_system_parallelism | |||||
struct none_below_threshold_t | struct none_below_threshold_t | ||||
{ | { | ||||
template<typename T_threshold, typename T_strategy> | template<typename T_threshold, typename T_strategy> | ||||
constexpr decltype(auto) operator()(T_threshold th, T_strategy s) const noexcept | |||||
constexpr decltype(auto) operator()(T_threshold th, T_strategy s) const noexcept | |||||
{ return fixed_threshold(th, none, s); } | { return fixed_threshold(th, none, s); } | ||||
}; | }; | ||||
} | } | ||||
@@ -38,10 +38,31 @@ beg_namespace_ecs_signature_system | |||||
return impl_type { }; | return impl_type { }; | ||||
} | } | ||||
public: | |||||
template<typename T_key> | |||||
constexpr decltype(auto) get(const T_key& key) const noexcept | |||||
{ return T_options { }.at(key); } | |||||
public: /* misc */ | |||||
constexpr decltype(auto) tag() const noexcept | constexpr decltype(auto) tag() const noexcept | ||||
{ return T_system_tag { }; } | { return T_system_tag { }; } | ||||
public: /* getter */ | |||||
constexpr decltype(auto) parallelism() const noexcept | |||||
{ return get(keys::parallelism); } | |||||
constexpr decltype(auto) dependencies() const noexcept | |||||
{ return get(keys::dependencies); } | |||||
constexpr decltype(auto) read() const noexcept | |||||
{ return get(keys::read_components); } | |||||
constexpr decltype(auto) write() const noexcept | |||||
{ return get(keys::write_components); } | |||||
constexpr decltype(auto) output() const noexcept | |||||
{ return get(keys::output); } | |||||
public: /* setter */ | |||||
template<typename T_parallelism> | template<typename T_parallelism> | ||||
constexpr decltype(auto) parallelism(T_parallelism parallelism) const noexcept | constexpr decltype(auto) parallelism(T_parallelism parallelism) const noexcept | ||||
{ return change(keys::parallelism, parallelism); } | { return change(keys::parallelism, parallelism); } | ||||
@@ -12,11 +12,14 @@ beg_namespace_ecs_signature_list_system | |||||
template<typename... T_system_signatures> | template<typename... T_system_signatures> | ||||
struct signature_list_t | struct signature_list_t | ||||
{ | { | ||||
public: | |||||
core::mp::list::type<T_system_signatures...> items; | core::mp::list::type<T_system_signatures...> items; | ||||
public: /* misc */ | |||||
constexpr decltype(auto) size() const noexcept | constexpr decltype(auto) size() const noexcept | ||||
{ return hana::size(items); } | { return hana::size(items); } | ||||
public: /* get */ | |||||
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 | ||||
{ | { | ||||
@@ -44,6 +47,19 @@ beg_namespace_ecs_signature_list_system | |||||
template<typename T_index> | template<typename T_index> | ||||
constexpr decltype(auto) get_by_index(T_index index) const noexcept | constexpr decltype(auto) get_by_index(T_index index) const noexcept | ||||
{ return hana::at(items, index); } | { return hana::at(items, index); } | ||||
public: /* id */ | |||||
template<typename T_system_signature> | |||||
constexpr decltype(auto) id_by_signature(T_system_signature ssig) const noexcept | |||||
{ return core::mp::list::index_of(items, ssig); } | |||||
template<typename T_system> | |||||
constexpr decltype(auto) id_by_type() const noexcept | |||||
{ return id_by_signature(get_by_type<T_system>()); } | |||||
template<typename T_system_tag> | |||||
constexpr decltype(auto) id_by_tag(T_system_tag st) const noexcept | |||||
{ return id_by_signature(signature_by_tag(st)); } | |||||
}; | }; | ||||
struct make_t | struct make_t | ||||
@@ -55,7 +71,7 @@ beg_namespace_ecs_signature_list_system | |||||
static_assert( | static_assert( | ||||
decltype(signature::system::is_valid(sss...)) { }, | decltype(signature::system::is_valid(sss...)) { }, | ||||
"system::signature_list::make() needs a list of system signatures"); | "system::signature_list::make() needs a list of system signatures"); | ||||
return signature_list_t<hana::type<T_system_signatures>...> { }; | |||||
return signature_list_t<hana::type<core::mp::decay_t<T_system_signatures>>...> { }; | |||||
} | } | ||||
}; | }; | ||||