1/* 2 * Copyright (c) 2023 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 OHOS_HDI_DISPLAY_V1_0_CACHE_MANAGER_H 17#define OHOS_HDI_DISPLAY_V1_0_CACHE_MANAGER_H 18 19#include <functional> 20#include <memory> 21#include <unordered_map> 22#include "hdf_log.h" 23#include "nocopyable.h" 24#include <mutex> 25#include "hdf_base.h" 26#include "hilog/log.h" 27#include "base/native_buffer.h" 28 29#undef LOG_TAG 30#define LOG_TAG "DISP_CACHE_MGR" 31#undef LOG_DOMAIN 32#define LOG_DOMAIN 0xD002515 33 34namespace OHOS { 35namespace HDI { 36namespace Display { 37namespace Composer { 38 39template <typename IdType, typename CacheType> 40class CacheManager : public NoCopyable { 41public: 42 CacheManager() 43 : cacheCountMax_ { 0 }, 44 cleanUpFunc_ { nullptr }, 45 initFunc_ { nullptr } 46 {} 47 48 virtual ~CacheManager() 49 { 50 std::lock_guard<std::mutex> lock(mutex_); 51 if (cleanUpFunc_) { 52 for (auto& cache : caches_) { 53 cleanUpFunc_(cache.second); 54 } 55 } 56 caches_.clear(); 57 } 58 59 bool SetCacheMaxCount(uint32_t count) 60 { 61 bool ret = true; 62 uint32_t originalMaxCount = cacheCountMax_; 63 if (count >= cacheCountMax_) { 64 cacheCountMax_ = count; 65 } else if (Size() <= count) { 66 cacheCountMax_ = count; 67 } else { 68 HDF_LOGE("%{public}s error: clientCacheCount can't be set, because cacheCountMax_ > count", __func__); 69 ret = false; 70 } 71 HDF_LOGD("%{public}s: set cache max count from %{public}u to %{public}u", 72 __func__, originalMaxCount, cacheCountMax_); 73 return ret; 74 } 75 76 uint32_t Size() 77 { 78 std::lock_guard<std::mutex> lock(mutex_); 79 return caches_.size(); 80 } 81 82 bool InsertCache(IdType id, CacheType* cache) 83 { 84 std::lock_guard<std::mutex> lock(mutex_); 85 auto cacheItem = caches_.find(id); 86 if (cacheItem != caches_.end()) { 87 HDF_LOGI("%{public}s: intend to insert a existing cache, SeqNo=%{public}d", __func__, id); 88 cacheItem->second.reset(cache); 89 } else { 90 if (cacheCountMax_ != 0 && caches_.size() >= cacheCountMax_) { 91 HDF_LOGE("%{public}s: Caches is full, new seqNo:%{public}d can't be inserted", __func__, id); 92 return false; 93 } 94 caches_[id] = std::move(std::unique_ptr<CacheType>(cache)); 95 } 96 if (initFunc_) { 97 initFunc_(caches_[id]); 98 } 99 return true; 100 } 101 102 bool EraseCache(IdType id) 103 { 104 std::lock_guard<std::mutex> lock(mutex_); 105 auto cacheItem = caches_.find(id); 106 if (cacheItem == caches_.end()) { 107 return false; 108 } 109 110 if (cleanUpFunc_ && cacheItem->second != nullptr) { 111 cleanUpFunc_(cacheItem->second); 112 } 113 114 caches_.erase(cacheItem); 115 return true; 116 } 117 118 CacheType* SearchCache(IdType id) 119 { 120 std::lock_guard<std::mutex> lock(mutex_); 121 auto cacheItem = caches_.find(id); 122 if (cacheItem == caches_.end()) { 123 return nullptr; 124 } 125 126 return cacheItem->second.get(); 127 } 128 129 void TravelCaches(std::function<void (IdType id, const CacheType& cache)> func) 130 { 131 std::lock_guard<std::mutex> lock(mutex_); 132 for (auto const& [key, value] : caches_) { 133 func(key, *value.get()); 134 } 135 } 136 137 void SetCleanUpFunc(void (*func)(std::unique_ptr<CacheType>&)) 138 { 139 cleanUpFunc_ = func; 140 } 141 142 void SetInitFunc(void (*func)(std::unique_ptr<CacheType>&)) 143 { 144 initFunc_ = func; 145 } 146 147private: 148 uint32_t cacheCountMax_; 149 std::unordered_map<IdType, std::unique_ptr<CacheType>> caches_; 150 void (*cleanUpFunc_)(std::unique_ptr<CacheType>&); 151 void (*initFunc_)(std::unique_ptr<CacheType>&); 152 std::mutex mutex_; 153}; 154 155template <typename IdType> 156class CacheManager<IdType, Base::NativeBuffer> : public NoCopyable { 157public: 158 CacheManager() 159 : cacheCountMax_ { 0 }, 160 cleanUpFunc_ { nullptr }, 161 initFunc_ { nullptr } 162 {} 163 164 virtual ~CacheManager() 165 { 166 std::lock_guard<std::mutex> lock(mutex_); 167 if (cleanUpFunc_) { 168 for (auto& cache : caches_) { 169 cleanUpFunc_(cache.second); 170 } 171 } 172 caches_.clear(); 173 } 174 175 bool SetCacheMaxCount(uint32_t count) 176 { 177 bool ret = true; 178 uint32_t originalMaxCount = cacheCountMax_; 179 if (count >= cacheCountMax_) { 180 cacheCountMax_ = count; 181 } else if (Size() <= count) { 182 cacheCountMax_ = count; 183 } else { 184 HDF_LOGE("%{public}s error: clientCacheCount can't be set, because cacheCountMax_ > count", __func__); 185 ret = false; 186 } 187 HDF_LOGI("%{public}s: set cache max count from %{public}u to %{public}u", 188 __func__, originalMaxCount, cacheCountMax_); 189 return ret; 190 } 191 192 uint32_t Size() 193 { 194 std::lock_guard<std::mutex> lock(mutex_); 195 return caches_.size(); 196 } 197 198 bool InsertCache(IdType id, Base::NativeBuffer* cache) 199 { 200 std::lock_guard<std::mutex> lock(mutex_); 201 auto cacheItem = caches_.find(id); 202 if (cacheItem != caches_.end()) { 203 HDF_LOGI("%{public}s: intend to insert a existing cache, SeqNo=%{public}d", __func__, id); 204 cacheItem->second = OHOS::sptr<Base::NativeBuffer>(cache); 205 } else { 206 if (cacheCountMax_ != 0 && caches_.size() >= cacheCountMax_) { 207 HDF_LOGE("%{public}s: Caches is full, new seqNo:%{public}d can't be inserted", __func__, id); 208 return false; 209 } 210 caches_[id] = OHOS::sptr<Base::NativeBuffer>(cache); 211 } 212 if (initFunc_) { 213 initFunc_(caches_[id]); 214 } 215 return true; 216 } 217 218 bool EraseCache(IdType id) 219 { 220 std::lock_guard<std::mutex> lock(mutex_); 221 auto cacheItem = caches_.find(id); 222 if (cacheItem == caches_.end()) { 223 HDF_LOGE("%{public}s: Cache %{public}d is not existing\n", __func__, id); 224 return false; 225 } 226 227 if (cleanUpFunc_ && cacheItem->second != nullptr) { 228 cleanUpFunc_(cacheItem->second); 229 } 230 231 caches_.erase(cacheItem); 232 return true; 233 } 234 235 Base::NativeBuffer* SearchCache(IdType id) 236 { 237 std::lock_guard<std::mutex> lock(mutex_); 238 auto cacheItem = caches_.find(id); 239 if (cacheItem == caches_.end()) { 240 return nullptr; 241 } 242 243 return cacheItem->second.GetRefPtr(); 244 } 245 246 void TravelCaches(std::function<void (IdType id, const Base::NativeBuffer& cache)> func) 247 { 248 std::lock_guard<std::mutex> lock(mutex_); 249 for (auto const& [key, value] : caches_) { 250 func(key, *value.GetRefPtr()); 251 } 252 } 253 254 void SetCleanUpFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&)) 255 { 256 cleanUpFunc_ = func; 257 } 258 259 void SetInitFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&)) 260 { 261 initFunc_ = func; 262 } 263 264private: 265 uint32_t cacheCountMax_; 266 std::unordered_map<IdType, OHOS::sptr<Base::NativeBuffer>> caches_; 267 void (*cleanUpFunc_)(OHOS::sptr<Base::NativeBuffer>&); 268 void (*initFunc_)(OHOS::sptr<Base::NativeBuffer>&); 269 std::mutex mutex_; 270}; 271} // namespace Composer 272} // namespace Display 273} // namespace HDI 274} // namespace OHOS 275#endif // OHOS_HDI_DISPLAY_V1_0_CACHE_MANAGER_H 276