/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef META_API_CONTAINER_FIND_CACHE_H
#define META_API_CONTAINER_FIND_CACHE_H
#include
#include
#include
#include
META_BEGIN_NAMESPACE()
/**
* @brief The FindCache class is a helper class for caching the results of a FindAny/FindAll operation on an IContainer.
*/
template
class FindCache {
public:
FindCache() = default;
~FindCache() = default;
/**
* @brief Sets the target for FindCache.
* @param container Target container.
* @param options Find options for IContainer::Find operation.
*/
void SetTarget(const META_NS::IContainer::ConstPtr& container, const META_NS::IContainer::FindOptions& options)
{
CORE_NS::UniqueLock lock(mutex_);
ResetTarget();
if (container) {
container_ = container;
options_ = options;
const auto cb = MakeCallback([this](const ChildChangedInfo&) { Invalidate(); });
addedHandler_.Subscribe(container->OnAdded(), cb);
removedHandler_.Subscribe(container->OnRemoved(), cb);
}
}
/**
* @brief Returns true if a valid target has been set.
*/
bool HasTarget() const noexcept
{
return !container_.expired();
}
/**
* @brief Calls IContainer::FindAny, caches and returns the result. Any subsequent FindAny calls return
* the cached result unless changes have been made to the container.
*/
typename Type::Ptr FindAny() const
{
CORE_NS::UniqueLock lock(mutex_);
if (const auto container = container_.lock()) {
if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ANY_CACHED)) {
resultAny_ = container->template FindAny(options_);
cached_.Set(CachedResultTypeBitsValue::FIND_ANY_CACHED);
}
return resultAny_;
}
return {};
}
/**
* @brief Calls IContainer::FindAll, caches and returns the result. Any subsequent FindAll calls return
* the cached result unless changes have been made to the container.
*/
BASE_NS::vector FindAll() const
{
CORE_NS::UniqueLock lock(mutex_);
if (const auto container = container_.lock()) {
if (!cached_.IsSet(CachedResultTypeBitsValue::FIND_ALL_CACHED)) {
resultAll_ = PtrArrayCast(container->FindAll(options_));
cached_.Set(CachedResultTypeBitsValue::FIND_ALL_CACHED);
}
return resultAll_;
}
return {};
}
/**
* @brief Invalidates the cached query results.
*/
void Invalidate()
{
CORE_NS::UniqueLock lock(mutex_);
ClearResults();
}
/**
* @brief Resets the cache (results and target).
*/
void Reset()
{
CORE_NS::UniqueLock lock(mutex_);
ResetTarget();
}
private:
void ResetTarget()
{
ClearResults();
container_.reset();
options_ = {};
}
void ClearResults()
{
resultAny_.reset();
resultAll_.clear();
cached_.Clear();
}
enum class CachedResultTypeBitsValue : uint16_t {
FIND_ANY_CACHED = 1,
FIND_ALL_CACHED = 2,
};
mutable CORE_NS::Mutex mutex_;
mutable EnumBitField cached_;
mutable typename Type::Ptr resultAny_;
mutable BASE_NS::vector resultAll_;
META_NS::IContainer::ConstWeakPtr container_;
META_NS::IContainer::FindOptions options_;
EventHandler addedHandler_;
EventHandler removedHandler_;
};
META_END_NAMESPACE()
#endif // META_API_CONTAINER_FIND_CACHE_H