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 HOLDER_MANAGER_H_
17 #define HOLDER_MANAGER_H_
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <map>
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <securec.h>
26 #include <type_traits>
27 
28 namespace OHOS {
29 namespace FileAccessFwk {
30 template<typename Type>
31 class HolderManager {
32 public:
33     static constexpr int CODE_CAN_NOT_FIND = 0;
HolderManager()34     HolderManager() {}
35 
~HolderManager()36     ~HolderManager()
37     {
38         std::lock_guard<std::mutex> guard(holderMutex_);
39         holder_.clear();
40         HILOG_INFO("~HolderManager holder size: %{public}zu", holder_.size());
41     }
42 
save(Type content)43     uint32_t save(Type content)
44     {
45         uint32_t id;
46         do {
47             id = genId();
48         } while (exist(id));
49         std::lock_guard<std::mutex> guard(holderMutex_);
50         holder_.insert(std::pair<uint32_t, Type>(id, content));
51         HILOG_INFO("save id:%{public}d holder size: %{public}zu", id, holder_.size());
52         return id;
53     }
54 
get(uint32_t id)55     Type get(uint32_t id)
56     {
57         std::lock_guard<std::mutex> guard(holderMutex_);
58         auto iter = holder_.find(id);
59         if (iter != holder_.end()) {
60             return iter->second;
61         }
62         return Type();
63     }
64 
pop(uint32_t id)65     Type pop(uint32_t id)
66     {
67         std::lock_guard<std::mutex> guard(holderMutex_);
68         auto iter = holder_.find(id);
69         if (iter != holder_.end()) {
70             auto res = iter->second;
71             holder_.erase(id);
72             HILOG_INFO("pop id: %{public}d find holder size: %{public}zu", id, holder_.size());
73             return res;
74         }
75         HILOG_INFO("pop id: %{public}d not find holder size: %{public}zu", id, holder_.size());
76         return Type();
77     }
78 
release(uint32_t id)79     void release(uint32_t id)
80     {
81         std::lock_guard<std::mutex> guard(holderMutex_);
82         if (holder_.count(id)) {
83             HILOG_INFO("release id: %{public}d find holder size: %{public}zu", id, holder_.size());
84             holder_.erase(id);
85         } else {
86             HILOG_INFO("release id: %{public}d not find holder size: %{public}zu", id, holder_.size());
87         }
88     }
89 
exist(uint32_t id)90     bool exist(uint32_t id)
91     {
92         std::lock_guard<std::mutex> guard(holderMutex_);
93         return holder_.count(id);
94     }
95 
getId(std::function<bool (const Type &)> func)96     uint32_t getId(std::function<bool(const Type &)> func)
97     {
98         auto haveIter = find_if(holder_.begin(), holder_.end(),
99             [func](const std::pair<uint32_t, Type> type) {
100                 return func(type.second);
101             });
102         if (haveIter == holder_.end()) {
103             return CODE_CAN_NOT_FIND;
104         }
105         return haveIter->first;
106     }
107 
getAll(std::vector<Type> & contexts)108     void getAll(std::vector<Type> &contexts)
109     {
110         std::lock_guard<std::mutex> guard(holderMutex_);
111         for (auto &iter : holder_) {
112             contexts.push_back(iter.second);
113         }
114     }
115 
isEmpty()116     bool isEmpty()
117     {
118         std::lock_guard<std::mutex> guard(holderMutex_);
119         return holder_.empty();
120     }
121 
122 private:
123     // key is automatic growth number
124     std::map<uint32_t, Type> holder_;
125     std::mutex holderMutex_;
126     std::atomic<uint32_t> gId_ = 1;
genId()127     uint32_t genId()
128     {
129         return gId_++;
130     }
131 };
132 } // namespace FileAccessFwk
133 } // namespace OHOS
134 #endif // FRAMEWORKS_INNERKITSIMPL_UTILS_INCLUDE_IMAGE_HOLDER_MANAGER_H_