1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_CORE_ECS_ENTITY_REFERENCE_H 17 #define API_CORE_ECS_ENTITY_REFERENCE_H 18 19 #include <cstdint> 20 21 #include <base/containers/refcnt_ptr.h> 22 #include <base/containers/type_traits.h> 23 #include <base/namespace.h> 24 #include <core/ecs/entity.h> 25 #include <core/namespace.h> 26 27 CORE_BEGIN_NAMESPACE() 28 class EntityReference; 29 30 /** Entity reference counter counter. */ 31 class IEntityReferenceCounter { 32 public: 33 using Ptr = BASE_NS::refcnt_ptr<IEntityReferenceCounter>; 34 virtual int32_t GetRefCount() const noexcept = 0; 35 36 protected: 37 virtual void Ref() noexcept = 0; 38 virtual void Unref() noexcept = 0; 39 40 friend Ptr; 41 friend EntityReference; 42 43 IEntityReferenceCounter() = default; 44 virtual ~IEntityReferenceCounter() = default; 45 IEntityReferenceCounter(const IEntityReferenceCounter&) = delete; 46 IEntityReferenceCounter& operator=(const IEntityReferenceCounter&) = delete; 47 IEntityReferenceCounter(IEntityReferenceCounter&&) = delete; 48 IEntityReferenceCounter& operator=(IEntityReferenceCounter&&) = delete; 49 }; 50 51 /** 52 * Helper for updating reference counts of shared entities. 53 */ 54 class EntityReference { 55 public: 56 /** Destructor releases the reference from the owning entity manager. 57 */ 58 ~EntityReference() = default; 59 60 /** Construct an empty reference. */ 61 EntityReference() = default; 62 63 /** Construct a reference for tracking the given entity. 64 * @param entity referenced entity 65 * @param counter Reference counter instance. 66 */ EntityReference(Entity entity,const IEntityReferenceCounter::Ptr & counter)67 EntityReference(Entity entity, const IEntityReferenceCounter::Ptr& counter) noexcept 68 : entity_(entity), counter_(counter) 69 {} 70 71 /** Copy a reference. Reference count will be increased. */ EntityReference(const EntityReference & other)72 EntityReference(const EntityReference& other) noexcept : entity_(other.entity_), counter_(other.counter_) {} 73 74 /** Move a reference. Moved from reference will be empty and reusable. */ EntityReference(EntityReference && other)75 EntityReference(EntityReference&& other) noexcept 76 : entity_(BASE_NS::exchange(other.entity_, Entity {})), counter_(BASE_NS::exchange(other.counter_, nullptr)) 77 {} 78 79 /** Copy a reference. Previous reference will be released and the one aquired. */ 80 EntityReference& operator=(const EntityReference& other) noexcept 81 { 82 if (&other != this) { 83 entity_ = other.entity_; 84 counter_ = other.counter_; 85 } 86 return *this; 87 } 88 89 /** Move a reference. Previous reference will be released and and the moved from reference will be empty and 90 * reusable. */ 91 EntityReference& operator=(EntityReference&& other) noexcept 92 { 93 if (&other != this) { 94 entity_ = BASE_NS::exchange(other.entity_, Entity {}); 95 counter_ = BASE_NS::exchange(other.counter_, nullptr); 96 } 97 return *this; 98 } 99 100 /** Get the referenced entity. */ Entity()101 operator Entity() const noexcept 102 { 103 return entity_; 104 } 105 106 /** Check validity of the reference. 107 * @return true if the reference is valid. 108 */ 109 explicit operator bool() const noexcept 110 { 111 return EntityUtil::IsValid(entity_) && (counter_); 112 } 113 114 /** Get ref count. Return 0, if invalid. 115 * @return Get reference count of render handle reference. 116 */ GetRefCount()117 int32_t GetRefCount() const noexcept 118 { 119 if (counter_) { 120 return counter_->GetRefCount(); 121 } 122 return 0; 123 } 124 125 private: 126 Entity entity_; 127 IEntityReferenceCounter::Ptr counter_; 128 }; 129 CORE_END_NAMESPACE() 130 131 #endif // API_CORE_ECS_ENTITY_REFERENCE_H 132