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