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 
34 namespace OHOS {
35 namespace HDI {
36 namespace Display {
37 namespace Composer {
38 
39 template <typename IdType, typename CacheType>
40 class CacheManager : public NoCopyable {
41 public:
CacheManager()42     CacheManager()
43         : cacheCountMax_ { 0 },
44           cleanUpFunc_ { nullptr },
45           initFunc_ { nullptr }
46     {}
47 
~CacheManager()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 
SetCacheMaxCount(uint32_t count)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 
Size()76     uint32_t Size()
77     {
78         std::lock_guard<std::mutex> lock(mutex_);
79         return caches_.size();
80     }
81 
InsertCache(IdType id, CacheType* cache)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 
EraseCache(IdType id)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 
SearchCache(IdType id)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 
TravelCaches(std::function<void (IdType id, const CacheType& cache)> func)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 
SetCleanUpFunc(void (*func)(std::unique_ptr<CacheType>&))137     void SetCleanUpFunc(void (*func)(std::unique_ptr<CacheType>&))
138     {
139         cleanUpFunc_ = func;
140     }
141 
SetInitFunc(void (*func)(std::unique_ptr<CacheType>&))142     void SetInitFunc(void (*func)(std::unique_ptr<CacheType>&))
143     {
144         initFunc_ = func;
145     }
146 
147 private:
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 
155 template <typename IdType>
156 class CacheManager<IdType, Base::NativeBuffer> : public NoCopyable {
157 public:
CacheManager()158     CacheManager()
159         : cacheCountMax_ { 0 },
160           cleanUpFunc_ { nullptr },
161           initFunc_ { nullptr }
162     {}
163 
~CacheManager()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 
SetCacheMaxCount(uint32_t count)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 
Size()192     uint32_t Size()
193     {
194         std::lock_guard<std::mutex> lock(mutex_);
195         return caches_.size();
196     }
197 
InsertCache(IdType id, Base::NativeBuffer* cache)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 
EraseCache(IdType id)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 
SearchCache(IdType id)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 
TravelCaches(std::function<void (IdType id, const Base::NativeBuffer& cache)> func)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 
SetCleanUpFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&))254     void SetCleanUpFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&))
255     {
256         cleanUpFunc_ = func;
257     }
258 
SetInitFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&))259     void SetInitFunc(void (*func)(OHOS::sptr<Base::NativeBuffer>&))
260     {
261         initFunc_ = func;
262     }
263 
264 private:
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