• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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     /** Construct a reference for tracking the given entity.
72      * @param entity referenced entity
73      * @param counter Reference counter instance.
74      */
EntityReference(Entity entity,IEntityReferenceCounter::Ptr && counter)75     EntityReference(Entity entity, IEntityReferenceCounter::Ptr&& counter) noexcept
76         : entity_(entity), counter_(BASE_NS::move(counter))
77     {}
78 
79     /** Copy a reference. Reference count will be increased. */
EntityReference(const EntityReference & other)80     EntityReference(const EntityReference& other) noexcept : entity_(other.entity_), counter_(other.counter_) {}
81 
82     /** Move a reference. Moved from reference will be empty and reusable. */
EntityReference(EntityReference && other)83     EntityReference(EntityReference&& other) noexcept
84         : entity_(BASE_NS::exchange(other.entity_, Entity {})), counter_(BASE_NS::exchange(other.counter_, nullptr))
85     {}
86 
87     /** Copy a reference. Previous reference will be released and the one aquired. */
88     EntityReference& operator=(const EntityReference& other) noexcept
89     {
90         if (&other != this) {
91             entity_ = other.entity_;
92             counter_ = other.counter_;
93         }
94         return *this;
95     }
96 
97     /** Move a reference. Previous reference will be released and and the moved from reference will be empty and
98      * reusable. */
99     EntityReference& operator=(EntityReference&& other) noexcept
100     {
101         if (&other != this) {
102             entity_ = BASE_NS::exchange(other.entity_, Entity {});
103             counter_ = BASE_NS::exchange(other.counter_, nullptr);
104         }
105         return *this;
106     }
107 
108     /** Get the referenced entity. */
Entity()109     operator Entity() const noexcept
110     {
111         return entity_;
112     }
113 
114     /** Check validity of the reference.
115      * @return true if the reference is valid.
116      */
117     explicit operator bool() const noexcept
118     {
119         return EntityUtil::IsValid(entity_) && (counter_);
120     }
121 
122     /** Get ref count. Return 0, if invalid.
123      * @return Get reference count of render handle reference.
124      */
GetRefCount()125     int32_t GetRefCount() const noexcept
126     {
127         if (counter_) {
128             return counter_->GetRefCount();
129         }
130         return 0;
131     }
132 
133 private:
134     Entity entity_;
135     IEntityReferenceCounter::Ptr counter_;
136 };
137 CORE_END_NAMESPACE()
138 
139 #endif // API_CORE_ECS_ENTITY_REFERENCE_H
140