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 changedHandler_.Subscribe(container->OnContainerChanged(), cb);
48 }
49 }
50 /**
51 * @brief Returns true if a valid target has been set.
52 */
53 bool HasTarget() const noexcept
54 {
55 return !container_.expired();
56 }
57 /**
58 * @brief Calls IContainer::FindAny, caches and returns the result. Any subsequent FindAny calls return
59 * the cached result unless changes have been made to the container.
60 */
61 typename Type::Ptr FindAny() const
62 {
63 CORE_NS::UniqueLock lock(mutex_);
64 if (const auto container = container_.lock()) {
65 if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ANY_CACHED)) {
66 resultAny_ = container->template FindAny<Type>(options_);
67 cached_.Set(CachedResultTypeBitsValue::FIND_ANY_CACHED);
68 }
69 return resultAny_;
70 }
71 return {};
72 }
73 /**
74 * @brief Calls IContainer::FindAll, caches and returns the result. Any subsequent FindAll calls return
75 * the cached result unless changes have been made to the container.
76 */
77 BASE_NS::vector<typename Type::Ptr> FindAll() const
78 {
79 CORE_NS::UniqueLock lock(mutex_);
80 if (const auto container = container_.lock()) {
81 if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ALL_CACHED)) {
82 resultAll_ = PtrArrayCast<Type>(container->FindAll(options_));
83 cached_.Set(CachedResultTypeBitsValue::FIND_ALL_CACHED);
84 }
85 return resultAll_;
86 }
87 return {};
88 }
89 /**
90 * @brief Invalidates the cached query results.
91 */
92 void Invalidate()
93 {
94 CORE_NS::UniqueLock lock(mutex_);
95 ClearResults();
96 }
97 /**
98 * @brief Resets the cache (results and target).
99 */
100 void Reset()
101 {
102 CORE_NS::UniqueLock lock(mutex_);
103 ResetTarget();
104 }
105
106 private:
107 void ResetTarget()
108 {
109 ClearResults();
110 container_.reset();
111 options_ = {};
112 }
113 void ClearResults()
114 {
115 resultAny_.reset();
116 resultAll_.clear();
117 cached_.Clear();
118 }
119 enum class CachedResultTypeBitsValue : uint16_t {
120 FIND_ANY_CACHED = 1,
121 FIND_ALL_CACHED = 2,
122 };
123
124 mutable CORE_NS::Mutex mutex_;
125 mutable EnumBitField<CachedResultTypeBitsValue> cached_;
126 mutable typename Type::Ptr resultAny_;
127 mutable BASE_NS::vector<typename Type::Ptr> resultAll_;
128 META_NS::IContainer::ConstWeakPtr container_;
129 META_NS::IContainer::FindOptions options_;
130 EventHandler changedHandler_;
131 };
132
133 META_END_NAMESPACE()
134
135 #endif // META_API_CONTAINER_FIND_CACHE_H
136