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 META_API_CONTAINER_FIND_CACHE_H
17 #define META_API_CONTAINER_FIND_CACHE_H
18 
19 #include <meta/api/event_handler.h>
20 #include <meta/api/internal/object_api.h>
21 #include <meta/api/threading/mutex.h>
22 #include <meta/interface/intf_container.h>
23 
META_BEGIN_NAMESPACE()24 META_BEGIN_NAMESPACE()
25 
26 /**
27  * @brief The FindCache class is a helper class for caching the results of a FindAny/FindAll operation on an IContainer.
28  */
29 template<class Type>
30 class FindCache {
31 public:
32     FindCache() = default;
33     ~FindCache() = default;
34     /**
35      * @brief Sets the target for FindCache.
36      * @param container Target container.
37      * @param options Find options for IContainer::Find operation.
38      */
39     void SetTarget(const META_NS::IContainer::ConstPtr& container, const META_NS::IContainer::FindOptions& options)
40     {
41         CORE_NS::UniqueLock lock(mutex_);
42         ResetTarget();
43         if (container) {
44             container_ = container;
45             options_ = options;
46             const auto cb = MakeCallback<IOnChildChanged>([this](const ChildChangedInfo&) { Invalidate(); });
47             addedHandler_.Subscribe(container->OnAdded(), cb);
48             removedHandler_.Subscribe(container->OnRemoved(), cb);
49         }
50     }
51     /**
52      * @brief Returns true if a valid target has been set.
53      */
54     bool HasTarget() const noexcept
55     {
56         return !container_.expired();
57     }
58     /**
59      * @brief Calls IContainer::FindAny, caches and returns the result. Any subsequent FindAny calls return
60      *        the cached result unless changes have been made to the container.
61      */
62     typename Type::Ptr FindAny() const
63     {
64         CORE_NS::UniqueLock lock(mutex_);
65         if (const auto container = container_.lock()) {
66             if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ANY_CACHED)) {
67                 resultAny_ = container->template FindAny<Type>(options_);
68                 cached_.Set(CachedResultTypeBitsValue::FIND_ANY_CACHED);
69             }
70             return resultAny_;
71         }
72         return {};
73     }
74     /**
75      * @brief Calls IContainer::FindAll, caches and returns the result. Any subsequent FindAll calls return
76      *        the cached result unless changes have been made to the container.
77      */
78     BASE_NS::vector<typename Type::Ptr> FindAll() const
79     {
80         CORE_NS::UniqueLock lock(mutex_);
81         if (const auto container = container_.lock()) {
82             if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ALL_CACHED)) {
83                 resultAll_ = PtrArrayCast<Type>(container->FindAll(options_));
84                 cached_.Set(CachedResultTypeBitsValue::FIND_ALL_CACHED);
85             }
86             return resultAll_;
87         }
88         return {};
89     }
90     /**
91      * @brief Invalidates the cached query results.
92      */
93     void Invalidate()
94     {
95         CORE_NS::UniqueLock lock(mutex_);
96         ClearResults();
97     }
98     /**
99      * @brief Resets the cache (results and target).
100      */
101     void Reset()
102     {
103         CORE_NS::UniqueLock lock(mutex_);
104         ResetTarget();
105     }
106 
107 private:
108     void ResetTarget()
109     {
110         ClearResults();
111         container_.reset();
112         options_ = {};
113     }
114     void ClearResults()
115     {
116         resultAny_.reset();
117         resultAll_.clear();
118         cached_.Clear();
119     }
120     enum class CachedResultTypeBitsValue : uint16_t {
121         FIND_ANY_CACHED = 1,
122         FIND_ALL_CACHED = 2,
123     };
124 
125     mutable CORE_NS::Mutex mutex_;
126     mutable EnumBitField<CachedResultTypeBitsValue> cached_;
127     mutable typename Type::Ptr resultAny_;
128     mutable BASE_NS::vector<typename Type::Ptr> resultAll_;
129     META_NS::IContainer::ConstWeakPtr container_;
130     META_NS::IContainer::FindOptions options_;
131     EventHandler addedHandler_;
132     EventHandler removedHandler_;
133 };
134 
135 META_END_NAMESPACE()
136 
137 #endif // META_API_CONTAINER_FIND_CACHE_H
138