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