|
- #pragma once
-
- #include <queue>
- #include <ecs/config.h>
- #include <ecs/core/utils/bitset.h>
-
- beg_namespace_ecs_core_entity_storage
- {
-
- struct entity_handle
- {
- private:
- uint32_t _index;
- uint32_t _counter;
-
- public:
- entity_handle(uint32_t i, uint32_t c)
- : _index (i)
- , _counter (c)
- { }
-
- inline auto index() const
- { return _index; }
-
- inline auto counter() const
- { return _counter; }
- };
-
- template <typename T_settings, typename T_chunk_meta_data>
- struct entity_meta_data
- {
- public:
- using bitset_type = utils::bitset<T_settings>;
- using chunk_meta_data_type = T_chunk_meta_data;
- using counter_type = uint32_t;
-
- private:
- bitset_type _bitset;
- counter_type _counter;
- chunk_meta_data_type _chunk_meta_data;
-
- public:
- entity_meta_data()
- : _counter(0)
- { }
-
- inline auto& bitset()
- { return _bitset; }
-
- inline auto counter() const
- { return _counter; }
-
- inline auto& chunk_meta_data()
- { return _chunk_meta_data; }
-
- inline void reset()
- {
- ++_counter;
- _bitset.clear();
- }
- };
-
- template<typename T_container_builder, typename T_settings, typename T_chunk_meta_data>
- struct base
- {
- public:
- using entity_handle_type = entity_handle;
- using entity_meta_data_type = entity_meta_data<T_settings, T_chunk_meta_data>;
-
- private:
- using container_type = typename T_container_builder::template type<entity_meta_data_type>;
- using queue_type = std::queue<uint32_t>;
-
- static constexpr decltype(auto) grow_size = 64;
-
- protected:
- container_type _container;
- queue_type _free_ids;
-
- private:
- inline void grow(size_t count)
- {
- auto old_size = _container.size();
- _container.resize(old_size + count);
- for (size_t i = old_size; i < _container.size(); ++i)
- {
- _free_ids.emplace(i);
- }
- }
-
- public:
- inline bool is_valid(const entity_handle& handle) const
- {
- return handle.index() < _container.size()
- && _container.at(handle.index()).counter() == handle.counter();
- }
-
- inline decltype(auto) claim()
- {
- if (_free_ids.empty())
- {
- grow(grow_size);
- }
- assert(!_free_ids.empty());
- auto index = _free_ids.back();
- auto& item = _container.at(index);
- _free_ids.pop();
- return entity_handle(index, item.counter());
- }
-
- inline void reclaim(const entity_handle& handle)
- {
- if (!is_valid(handle))
- throw std::invalid_argument("invalid entity handle");
- auto index = handle.index();
- auto& item = _container.at(index);
- item.reset();
- _free_ids.emplace(index);
- }
-
- inline void clear()
- {
- _free_ids = queue_type { };
- for (size_t i = 0; i < _container.size(); ++i)
- {
- _container.at(i).reset();
- _free_ids.emplace(i);
- }
- }
-
- inline auto& meta_data(const entity_handle& handle)
- {
- if (!is_valid(handle))
- throw std::invalid_argument("invalid entity handle");
- auto index = handle.index();
- return _container.at(index);
- }
-
- };
-
- }
- end_namespace_ecs_core_entity_storage
|