|
|
@@ -3,37 +3,198 @@ |
|
|
|
#include <ecs/config.h> |
|
|
|
#include <ecs/signature/system.h> |
|
|
|
#include <ecs/core/utils/bitset.h> |
|
|
|
#include <ecs/core/utils/fixed_function.h> |
|
|
|
|
|
|
|
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> |
|
|
|
struct instance |
|
|
|
{ |
|
|
|
static_assert(decltype(signature::system::is_valid(mp::unwrap_t<T_system_signature> { })) { }); |
|
|
|
|
|
|
|
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: |
|
|
|
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: |
|
|
|
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: |
|
|
|
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 |
|
|
|
{ return _system; } |
|
|
|
|
|
|
|
inline const auto& system() const noexcept |
|
|
|
{ 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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |