18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "entity_manager.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <atomic>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <base/containers/generic_iterator.h>
228bf80f4bSopenharmony_ci#include <base/containers/iterator.h>
238bf80f4bSopenharmony_ci#include <base/containers/refcnt_ptr.h>
248bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
258bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h>
268bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
278bf80f4bSopenharmony_ci#include <base/containers/vector.h>
288bf80f4bSopenharmony_ci#include <base/namespace.h>
298bf80f4bSopenharmony_ci#include <core/ecs/entity.h>
308bf80f4bSopenharmony_ci#include <core/ecs/entity_reference.h>
318bf80f4bSopenharmony_ci#include <core/ecs/intf_entity_manager.h>
328bf80f4bSopenharmony_ci#include <core/log.h>
338bf80f4bSopenharmony_ci#include <core/namespace.h>
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE()
368bf80f4bSopenharmony_ciusing BASE_NS::pair;
378bf80f4bSopenharmony_ciusing BASE_NS::vector;
388bf80f4bSopenharmony_ci
398bf80f4bSopenharmony_cinamespace {
408bf80f4bSopenharmony_ciuint32_t GetId(const Entity& e)
418bf80f4bSopenharmony_ci{
428bf80f4bSopenharmony_ci    return e.id & 0xFFFFFFFF;
438bf80f4bSopenharmony_ci}
448bf80f4bSopenharmony_ci
458bf80f4bSopenharmony_ciuint32_t GetGeneration(const Entity& e)
468bf80f4bSopenharmony_ci{
478bf80f4bSopenharmony_ci    return (e.id >> 32l) & 0xFFFFFFFF;
488bf80f4bSopenharmony_ci}
498bf80f4bSopenharmony_ci
508bf80f4bSopenharmony_ciEntity MakeEntityId(uint32_t g, uint32_t i)
518bf80f4bSopenharmony_ci{
528bf80f4bSopenharmony_ci    return { (static_cast<uint64_t>(g) << 32l) | i };
538bf80f4bSopenharmony_ci}
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ciclass EntityReferenceCounter final : public IEntityReferenceCounter {
568bf80f4bSopenharmony_cipublic:
578bf80f4bSopenharmony_ci    using Ptr = BASE_NS::refcnt_ptr<EntityReferenceCounter>;
588bf80f4bSopenharmony_ci    EntityReferenceCounter() = default;
598bf80f4bSopenharmony_ci    ~EntityReferenceCounter() override = default;
608bf80f4bSopenharmony_ci    EntityReferenceCounter(const EntityReferenceCounter&) = delete;
618bf80f4bSopenharmony_ci    EntityReferenceCounter& operator=(const EntityReferenceCounter&) = delete;
628bf80f4bSopenharmony_ci    EntityReferenceCounter(EntityReferenceCounter&&) = delete;
638bf80f4bSopenharmony_ci    EntityReferenceCounter& operator=(EntityReferenceCounter&&) = delete;
648bf80f4bSopenharmony_ci
658bf80f4bSopenharmony_ciprotected:
668bf80f4bSopenharmony_ci    void Ref() noexcept override
678bf80f4bSopenharmony_ci    {
688bf80f4bSopenharmony_ci        refcnt_.fetch_add(1, std::memory_order_relaxed);
698bf80f4bSopenharmony_ci    }
708bf80f4bSopenharmony_ci
718bf80f4bSopenharmony_ci    void Unref() noexcept override
728bf80f4bSopenharmony_ci    {
738bf80f4bSopenharmony_ci        if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 0) {
748bf80f4bSopenharmony_ci            std::atomic_thread_fence(std::memory_order_acquire);
758bf80f4bSopenharmony_ci            delete this;
768bf80f4bSopenharmony_ci        }
778bf80f4bSopenharmony_ci    }
788bf80f4bSopenharmony_ci
798bf80f4bSopenharmony_ci    int32_t GetRefCount() const noexcept override
808bf80f4bSopenharmony_ci    {
818bf80f4bSopenharmony_ci        return refcnt_.load();
828bf80f4bSopenharmony_ci    }
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_ciprivate:
858bf80f4bSopenharmony_ci    std::atomic<int32_t> refcnt_ { -1 };
868bf80f4bSopenharmony_ci};
878bf80f4bSopenharmony_ci} // namespace
888bf80f4bSopenharmony_ci
898bf80f4bSopenharmony_ciEntityManager::EntityManager() : EntityManager(64u) {}
908bf80f4bSopenharmony_ci
918bf80f4bSopenharmony_ciEntityManager::EntityManager(const size_t entityCount)
928bf80f4bSopenharmony_ci{
938bf80f4bSopenharmony_ci    entities_.reserve(entityCount);
948bf80f4bSopenharmony_ci}
958bf80f4bSopenharmony_ci
968bf80f4bSopenharmony_ciEntityManager::~EntityManager()
978bf80f4bSopenharmony_ci{
988bf80f4bSopenharmony_ci    // count live entities, should be zero
998bf80f4bSopenharmony_ci    [[maybe_unused]] int32_t liveEntities = 0;
1008bf80f4bSopenharmony_ci    [[maybe_unused]] int32_t inactiveEntities = 0;
1018bf80f4bSopenharmony_ci    for (const auto& e : entities_) {
1028bf80f4bSopenharmony_ci        if (EntityState::State::ALIVE == e.state) {
1038bf80f4bSopenharmony_ci            ++liveEntities;
1048bf80f4bSopenharmony_ci        }
1058bf80f4bSopenharmony_ci        if (EntityState::State::INACTIVE == e.state) {
1068bf80f4bSopenharmony_ci            ++inactiveEntities;
1078bf80f4bSopenharmony_ci        }
1088bf80f4bSopenharmony_ci    }
1098bf80f4bSopenharmony_ci    CORE_ASSERT(inactiveEntities == 0);
1108bf80f4bSopenharmony_ci    CORE_ASSERT(liveEntities == 0);
1118bf80f4bSopenharmony_ci}
1128bf80f4bSopenharmony_ci
1138bf80f4bSopenharmony_ciEntity EntityManager::Create()
1148bf80f4bSopenharmony_ci{
1158bf80f4bSopenharmony_ci    Entity result;
1168bf80f4bSopenharmony_ci    if (freeList_.empty()) {
1178bf80f4bSopenharmony_ci        const auto generation = 1U;
1188bf80f4bSopenharmony_ci        const auto id = static_cast<uint32_t>(entities_.size());
1198bf80f4bSopenharmony_ci        entities_.push_back({ EntityState::State::ALIVE, generation, nullptr });
1208bf80f4bSopenharmony_ci        result = MakeEntityId(generation, id);
1218bf80f4bSopenharmony_ci    } else {
1228bf80f4bSopenharmony_ci        const auto id = freeList_.back();
1238bf80f4bSopenharmony_ci        freeList_.pop_back();
1248bf80f4bSopenharmony_ci        auto& slot = entities_[id];
1258bf80f4bSopenharmony_ci        // if the slot isn't free report a dead entity
1268bf80f4bSopenharmony_ci        if (slot.state != EntityState::State::FREE) {
1278bf80f4bSopenharmony_ci            const auto deadEntity = MakeEntityId(slot.generation, id);
1288bf80f4bSopenharmony_ci            removedList_.push_back(deadEntity);
1298bf80f4bSopenharmony_ci            eventList_.push_back({ deadEntity, EventType::DESTROYED });
1308bf80f4bSopenharmony_ci        }
1318bf80f4bSopenharmony_ci        slot.counter = nullptr; // NOTE: could push to a pool and recycle used often
1328bf80f4bSopenharmony_ci        ++slot.generation;
1338bf80f4bSopenharmony_ci
1348bf80f4bSopenharmony_ci        slot.state = EntityState::State::ALIVE;
1358bf80f4bSopenharmony_ci        result = MakeEntityId(slot.generation, id);
1368bf80f4bSopenharmony_ci    }
1378bf80f4bSopenharmony_ci    eventList_.push_back({ result, EventType::CREATED });
1388bf80f4bSopenharmony_ci    ++generationCounter_;
1398bf80f4bSopenharmony_ci    return result;
1408bf80f4bSopenharmony_ci}
1418bf80f4bSopenharmony_ci
1428bf80f4bSopenharmony_ciEntityReference EntityManager::CreateReferenceCounted()
1438bf80f4bSopenharmony_ci{
1448bf80f4bSopenharmony_ci    Entity result;
1458bf80f4bSopenharmony_ci    if (freeList_.empty()) {
1468bf80f4bSopenharmony_ci        const auto generation = 1U;
1478bf80f4bSopenharmony_ci        const auto id = static_cast<uint32_t>(entities_.size());
1488bf80f4bSopenharmony_ci        entities_.push_back(
1498bf80f4bSopenharmony_ci            { EntityState::State::ALIVE, generation, IEntityReferenceCounter::Ptr { new EntityReferenceCounter } });
1508bf80f4bSopenharmony_ci        result = MakeEntityId(generation, id);
1518bf80f4bSopenharmony_ci    } else {
1528bf80f4bSopenharmony_ci        const auto id = freeList_.back();
1538bf80f4bSopenharmony_ci        freeList_.pop_back();
1548bf80f4bSopenharmony_ci        auto& slot = entities_[id];
1558bf80f4bSopenharmony_ci
1568bf80f4bSopenharmony_ci        // if the slot isn't free report a dead entity
1578bf80f4bSopenharmony_ci        if (slot.state != EntityState::State::FREE) {
1588bf80f4bSopenharmony_ci            const auto deadEntity = MakeEntityId(slot.generation, id);
1598bf80f4bSopenharmony_ci            removedList_.push_back(deadEntity);
1608bf80f4bSopenharmony_ci            eventList_.push_back({ deadEntity, EventType::DESTROYED });
1618bf80f4bSopenharmony_ci        }
1628bf80f4bSopenharmony_ci        if (!slot.counter) {
1638bf80f4bSopenharmony_ci            slot.counter.reset(new EntityReferenceCounter);
1648bf80f4bSopenharmony_ci        }
1658bf80f4bSopenharmony_ci        ++slot.generation;
1668bf80f4bSopenharmony_ci        slot.state = EntityState::State::ALIVE;
1678bf80f4bSopenharmony_ci        result = MakeEntityId(slot.generation, id);
1688bf80f4bSopenharmony_ci    }
1698bf80f4bSopenharmony_ci    eventList_.push_back({ result, EventType::CREATED });
1708bf80f4bSopenharmony_ci    ++generationCounter_;
1718bf80f4bSopenharmony_ci    return EntityReference(result, entities_[GetId(result)].counter);
1728bf80f4bSopenharmony_ci}
1738bf80f4bSopenharmony_ci
1748bf80f4bSopenharmony_ciEntityReference EntityManager::GetReferenceCounted(const Entity entity)
1758bf80f4bSopenharmony_ci{
1768bf80f4bSopenharmony_ci    if (EntityUtil::IsValid(entity)) {
1778bf80f4bSopenharmony_ci        if (const uint32_t id = GetId(entity); id < entities_.size()) {
1788bf80f4bSopenharmony_ci            auto& e = entities_[id];
1798bf80f4bSopenharmony_ci            // make sure the given entity id has the same generation and that the entity isn't dead or free.
1808bf80f4bSopenharmony_ci            if ((e.generation == GetGeneration(entity)) &&
1818bf80f4bSopenharmony_ci                ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) {
1828bf80f4bSopenharmony_ci                if (!e.counter) {
1838bf80f4bSopenharmony_ci                    // entity wasn't yet reference counted so add a counter
1848bf80f4bSopenharmony_ci                    e.counter.reset(new EntityReferenceCounter);
1858bf80f4bSopenharmony_ci                    return { entity, e.counter };
1868bf80f4bSopenharmony_ci                }
1878bf80f4bSopenharmony_ci                if (e.counter->GetRefCount() > 0) {
1888bf80f4bSopenharmony_ci                    // reference count is still valid
1898bf80f4bSopenharmony_ci                    return { entity, e.counter };
1908bf80f4bSopenharmony_ci                }
1918bf80f4bSopenharmony_ci                // reference count has expired, but we won't revive the entity.
1928bf80f4bSopenharmony_ci            }
1938bf80f4bSopenharmony_ci        }
1948bf80f4bSopenharmony_ci    }
1958bf80f4bSopenharmony_ci    return {};
1968bf80f4bSopenharmony_ci}
1978bf80f4bSopenharmony_ci
1988bf80f4bSopenharmony_civoid EntityManager::Destroy(const Entity entity)
1998bf80f4bSopenharmony_ci{
2008bf80f4bSopenharmony_ci    if (EntityUtil::IsValid(entity)) {
2018bf80f4bSopenharmony_ci        if (const uint32_t id = GetId(entity); id < entities_.size()) {
2028bf80f4bSopenharmony_ci            auto& e = entities_[id];
2038bf80f4bSopenharmony_ci            if ((e.generation == GetGeneration(entity)) &&
2048bf80f4bSopenharmony_ci                ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) {
2058bf80f4bSopenharmony_ci                e.state = EntityState::State::DEAD;
2068bf80f4bSopenharmony_ci                e.counter = nullptr;
2078bf80f4bSopenharmony_ci                removedList_.push_back(entity);
2088bf80f4bSopenharmony_ci                eventList_.push_back({ entity, EventType::DESTROYED });
2098bf80f4bSopenharmony_ci                ++generationCounter_;
2108bf80f4bSopenharmony_ci            }
2118bf80f4bSopenharmony_ci        }
2128bf80f4bSopenharmony_ci    }
2138bf80f4bSopenharmony_ci}
2148bf80f4bSopenharmony_ci
2158bf80f4bSopenharmony_civoid EntityManager::DestroyAllEntities()
2168bf80f4bSopenharmony_ci{
2178bf80f4bSopenharmony_ci    for (uint32_t i = 0, count = static_cast<uint32_t>(entities_.size()); i < count; ++i) {
2188bf80f4bSopenharmony_ci        auto& e = entities_[i];
2198bf80f4bSopenharmony_ci        if ((EntityState::State::ALIVE == e.state) || (EntityState::State::INACTIVE == e.state)) {
2208bf80f4bSopenharmony_ci            auto entity = MakeEntityId(e.generation, i);
2218bf80f4bSopenharmony_ci            removedList_.push_back(entity);
2228bf80f4bSopenharmony_ci            eventList_.push_back({ entity, EventType::DESTROYED });
2238bf80f4bSopenharmony_ci            e.counter = nullptr;
2248bf80f4bSopenharmony_ci            e.state = EntityState::State::DEAD;
2258bf80f4bSopenharmony_ci        }
2268bf80f4bSopenharmony_ci    }
2278bf80f4bSopenharmony_ci    ++generationCounter_;
2288bf80f4bSopenharmony_ci}
2298bf80f4bSopenharmony_ci
2308bf80f4bSopenharmony_cibool EntityManager::IsAlive(const Entity entity) const
2318bf80f4bSopenharmony_ci{
2328bf80f4bSopenharmony_ci    if (EntityUtil::IsValid(entity)) {
2338bf80f4bSopenharmony_ci        const uint32_t id = GetId(entity);
2348bf80f4bSopenharmony_ci        if (id < entities_.size()) {
2358bf80f4bSopenharmony_ci            const auto& state = entities_[id];
2368bf80f4bSopenharmony_ci            if (state.generation == GetGeneration(entity)) {
2378bf80f4bSopenharmony_ci                return (state.state == EntityState::State::ALIVE) &&
2388bf80f4bSopenharmony_ci                       (!state.counter || (state.counter->GetRefCount() > 0));
2398bf80f4bSopenharmony_ci            }
2408bf80f4bSopenharmony_ci        }
2418bf80f4bSopenharmony_ci    }
2428bf80f4bSopenharmony_ci    return false;
2438bf80f4bSopenharmony_ci}
2448bf80f4bSopenharmony_ci
2458bf80f4bSopenharmony_civector<Entity> EntityManager::GetRemovedEntities()
2468bf80f4bSopenharmony_ci{
2478bf80f4bSopenharmony_ci    const auto freeSize = freeList_.size();
2488bf80f4bSopenharmony_ci    for (const Entity& e : removedList_) {
2498bf80f4bSopenharmony_ci        const uint32_t id = GetId(e);
2508bf80f4bSopenharmony_ci        if (id < entities_.size()) {
2518bf80f4bSopenharmony_ci            if (entities_[id].generation == GetGeneration(e)) {
2528bf80f4bSopenharmony_ci                CORE_ASSERT(entities_[id].state == EntityState::State::DEAD);
2538bf80f4bSopenharmony_ci                if (id < entities_.size() - 1) {
2548bf80f4bSopenharmony_ci                    entities_[id].state = EntityState::State::FREE;
2558bf80f4bSopenharmony_ci                    freeList_.push_back(id);
2568bf80f4bSopenharmony_ci                } else {
2578bf80f4bSopenharmony_ci                    entities_.resize(entities_.size() - 1);
2588bf80f4bSopenharmony_ci                }
2598bf80f4bSopenharmony_ci            }
2608bf80f4bSopenharmony_ci        }
2618bf80f4bSopenharmony_ci    }
2628bf80f4bSopenharmony_ci    if (const auto finalFreeSize = freeList_.size()) {
2638bf80f4bSopenharmony_ci        // by sorting with greater and using pop_back in creation we keep entities_ filled from the beginning.
2648bf80f4bSopenharmony_ci        // could be removed not useful.
2658bf80f4bSopenharmony_ci        if (finalFreeSize != freeSize) {
2668bf80f4bSopenharmony_ci            std::sort(freeList_.begin(), freeList_.end(), std::greater {});
2678bf80f4bSopenharmony_ci        }
2688bf80f4bSopenharmony_ci        // check from the beginning that ids don't go out-of-bounds and remove problematic ones.
2698bf80f4bSopenharmony_ci        // most likely they never are so linear is better than lower_bounds.
2708bf80f4bSopenharmony_ci        auto count = 0U;
2718bf80f4bSopenharmony_ci        while ((count < finalFreeSize) && (freeList_[count] >= entities_.size())) {
2728bf80f4bSopenharmony_ci            ++count;
2738bf80f4bSopenharmony_ci        }
2748bf80f4bSopenharmony_ci        if (count) {
2758bf80f4bSopenharmony_ci            freeList_.erase(freeList_.cbegin(), freeList_.cbegin() + count);
2768bf80f4bSopenharmony_ci        }
2778bf80f4bSopenharmony_ci    }
2788bf80f4bSopenharmony_ci    return move(removedList_);
2798bf80f4bSopenharmony_ci}
2808bf80f4bSopenharmony_ci
2818bf80f4bSopenharmony_ciuint32_t EntityManager::GetGenerationCounter() const
2828bf80f4bSopenharmony_ci{
2838bf80f4bSopenharmony_ci    return generationCounter_;
2848bf80f4bSopenharmony_ci}
2858bf80f4bSopenharmony_ci
2868bf80f4bSopenharmony_civector<pair<Entity, IEntityManager::EventType>> EntityManager::GetEvents()
2878bf80f4bSopenharmony_ci{
2888bf80f4bSopenharmony_ci    return move(eventList_);
2898bf80f4bSopenharmony_ci}
2908bf80f4bSopenharmony_ci
2918bf80f4bSopenharmony_civoid EntityManager::SetActive(const Entity entity, bool state)
2928bf80f4bSopenharmony_ci{
2938bf80f4bSopenharmony_ci    if (EntityUtil::IsValid(entity)) {
2948bf80f4bSopenharmony_ci        EntityState::State oldState;
2958bf80f4bSopenharmony_ci        EntityState::State newState;
2968bf80f4bSopenharmony_ci        EventType event;
2978bf80f4bSopenharmony_ci        if (state) {
2988bf80f4bSopenharmony_ci            oldState = EntityState::State::INACTIVE;
2998bf80f4bSopenharmony_ci            newState = EntityState::State::ALIVE;
3008bf80f4bSopenharmony_ci            event = EventType::ACTIVATED;
3018bf80f4bSopenharmony_ci        } else {
3028bf80f4bSopenharmony_ci            oldState = EntityState::State::ALIVE;
3038bf80f4bSopenharmony_ci            newState = EntityState::State::INACTIVE;
3048bf80f4bSopenharmony_ci            event = EventType::DEACTIVATED;
3058bf80f4bSopenharmony_ci        }
3068bf80f4bSopenharmony_ci
3078bf80f4bSopenharmony_ci        uint32_t id = GetId(entity);
3088bf80f4bSopenharmony_ci        if (id < entities_.size()) {
3098bf80f4bSopenharmony_ci            if (entities_[id].generation == GetGeneration(entity)) {
3108bf80f4bSopenharmony_ci                if (entities_[id].state == oldState) {
3118bf80f4bSopenharmony_ci                    entities_[id].state = newState;
3128bf80f4bSopenharmony_ci                    eventList_.push_back({ entity, event });
3138bf80f4bSopenharmony_ci                    ++generationCounter_;
3148bf80f4bSopenharmony_ci                }
3158bf80f4bSopenharmony_ci            }
3168bf80f4bSopenharmony_ci        }
3178bf80f4bSopenharmony_ci    }
3188bf80f4bSopenharmony_ci}
3198bf80f4bSopenharmony_ci
3208bf80f4bSopenharmony_civoid EntityManager::UpdateDeadEntities()
3218bf80f4bSopenharmony_ci{
3228bf80f4bSopenharmony_ci    const auto removedCount = removedList_.size();
3238bf80f4bSopenharmony_ci    for (uint32_t id = 0, count = static_cast<uint32_t>(entities_.size()); id < count; ++id) {
3248bf80f4bSopenharmony_ci        auto& e = entities_[id];
3258bf80f4bSopenharmony_ci        if ((e.state != EntityState::State::FREE) && e.counter && (e.counter->GetRefCount() == 0)) {
3268bf80f4bSopenharmony_ci            const Entity entity = MakeEntityId(e.generation, id);
3278bf80f4bSopenharmony_ci            removedList_.push_back(entity);
3288bf80f4bSopenharmony_ci            eventList_.push_back({ entity, EventType::DESTROYED });
3298bf80f4bSopenharmony_ci            e.state = EntityState::State::DEAD;
3308bf80f4bSopenharmony_ci        }
3318bf80f4bSopenharmony_ci    }
3328bf80f4bSopenharmony_ci    if (removedCount != removedList_.size()) {
3338bf80f4bSopenharmony_ci        ++generationCounter_;
3348bf80f4bSopenharmony_ci    }
3358bf80f4bSopenharmony_ci}
3368bf80f4bSopenharmony_ci
3378bf80f4bSopenharmony_ciEntityManager::IteratorImpl::IteratorImpl(const EntityManager& owner, size_t index, IteratorType type)
3388bf80f4bSopenharmony_ci    : owner_(&owner), index_(static_cast<uint32_t>(index)), type_(type)
3398bf80f4bSopenharmony_ci{
3408bf80f4bSopenharmony_ci    const auto valid = (type == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE;
3418bf80f4bSopenharmony_ci    if (index < owner.entities_.size()) {
3428bf80f4bSopenharmony_ci        const auto& e = owner.entities_[index];
3438bf80f4bSopenharmony_ci        if ((e.state != valid) || (e.counter && e.counter->GetRefCount() == 0)) {
3448bf80f4bSopenharmony_ci            Next();
3458bf80f4bSopenharmony_ci        }
3468bf80f4bSopenharmony_ci    }
3478bf80f4bSopenharmony_ci}
3488bf80f4bSopenharmony_ci
3498bf80f4bSopenharmony_ciconst class IEntityManager* EntityManager::IteratorImpl::GetOwner() const
3508bf80f4bSopenharmony_ci{
3518bf80f4bSopenharmony_ci    return owner_;
3528bf80f4bSopenharmony_ci}
3538bf80f4bSopenharmony_ci
3548bf80f4bSopenharmony_cibool EntityManager::IteratorImpl::Compare(const Iterator::Ptr& other) const
3558bf80f4bSopenharmony_ci{
3568bf80f4bSopenharmony_ci    if ((other == nullptr) || (other->GetOwner() != owner_)) {
3578bf80f4bSopenharmony_ci        return false;
3588bf80f4bSopenharmony_ci    }
3598bf80f4bSopenharmony_ci    auto* otheri = static_cast<const EntityManager::IteratorImpl*>(other.get());
3608bf80f4bSopenharmony_ci    return (index_ == otheri->index_) && (type_ == otheri->type_);
3618bf80f4bSopenharmony_ci}
3628bf80f4bSopenharmony_ci
3638bf80f4bSopenharmony_cibool EntityManager::IteratorImpl::Next()
3648bf80f4bSopenharmony_ci{
3658bf80f4bSopenharmony_ci    const auto& entities = owner_->entities_;
3668bf80f4bSopenharmony_ci    if (index_ < entities.size()) {
3678bf80f4bSopenharmony_ci        const auto valid =
3688bf80f4bSopenharmony_ci            (type_ == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE;
3698bf80f4bSopenharmony_ci
3708bf80f4bSopenharmony_ci        ++index_;
3718bf80f4bSopenharmony_ci        while (index_ < entities.size()) {
3728bf80f4bSopenharmony_ci            auto& state = entities[index_];
3738bf80f4bSopenharmony_ci            if ((state.state == valid) && ((!state.counter) || (state.counter->GetRefCount() > 0))) {
3748bf80f4bSopenharmony_ci                break;
3758bf80f4bSopenharmony_ci            }
3768bf80f4bSopenharmony_ci            ++index_;
3778bf80f4bSopenharmony_ci        }
3788bf80f4bSopenharmony_ci    }
3798bf80f4bSopenharmony_ci    return (index_ < owner_->entities_.size());
3808bf80f4bSopenharmony_ci}
3818bf80f4bSopenharmony_ci
3828bf80f4bSopenharmony_ciEntity EntityManager::IteratorImpl::Get() const
3838bf80f4bSopenharmony_ci{
3848bf80f4bSopenharmony_ci    if (index_ >= owner_->entities_.size()) {
3858bf80f4bSopenharmony_ci        return {};
3868bf80f4bSopenharmony_ci    }
3878bf80f4bSopenharmony_ci    return MakeEntityId(owner_->entities_[index_].generation, index_);
3888bf80f4bSopenharmony_ci}
3898bf80f4bSopenharmony_ci
3908bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::MakeIterator(uint32_t index, IteratorType type) const
3918bf80f4bSopenharmony_ci{
3928bf80f4bSopenharmony_ci    auto del = [](Iterator* it) { delete static_cast<EntityManager::IteratorImpl*>(it); };
3938bf80f4bSopenharmony_ci    auto p = new EntityManager::IteratorImpl(*this, index, type);
3948bf80f4bSopenharmony_ci    return { p, del };
3958bf80f4bSopenharmony_ci}
3968bf80f4bSopenharmony_ci
3978bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::IteratorImpl::Clone() const
3988bf80f4bSopenharmony_ci{
3998bf80f4bSopenharmony_ci    return owner_->MakeIterator(index_, type_);
4008bf80f4bSopenharmony_ci}
4018bf80f4bSopenharmony_ci
4028bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::Begin(IteratorType type) const
4038bf80f4bSopenharmony_ci{
4048bf80f4bSopenharmony_ci    return MakeIterator(0U, type);
4058bf80f4bSopenharmony_ci}
4068bf80f4bSopenharmony_ci
4078bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::End(IteratorType type) const
4088bf80f4bSopenharmony_ci{
4098bf80f4bSopenharmony_ci    return MakeIterator(static_cast<uint32_t>(entities_.size()), type);
4108bf80f4bSopenharmony_ci}
4118bf80f4bSopenharmony_ci
4128bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
413