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 APP_DOMAIN_VERIFY_SAFEMAP_H 17 #define APP_DOMAIN_VERIFY_SAFEMAP_H 18 #include <map> 19 #include "ffrt.h" 20 21 namespace OHOS::AppDomainVerify { 22 23 /** 24 * @brief Provides interfaces for thread-safe map operations with ffrt. 25 */ 26 template <typename K, typename V> 27 class SafeMap { 28 public: SafeMap()29 SafeMap() {} 30 ~SafeMap()31 ~SafeMap() {} 32 SafeMap(const SafeMap & rhs)33 SafeMap(const SafeMap& rhs) 34 { 35 map_ = rhs.map_; 36 } 37 38 SafeMap& operator=(const SafeMap& rhs) 39 { 40 if (&rhs != this) { 41 map_ = rhs.map_; 42 } 43 44 return *this; 45 } 46 ReadVal(const K & key)47 V ReadVal(const K& key) 48 { 49 std::lock_guard<ffrt::mutex> lock(mutex_); 50 return map_[key]; 51 } 52 53 template<typename LambdaCallback> ChangeValueByLambda(const K & key,LambdaCallback callback)54 void ChangeValueByLambda(const K& key, LambdaCallback callback) 55 { 56 std::lock_guard<ffrt::mutex> lock(mutex_); 57 callback(map_[key]); 58 } 59 60 /** 61 * @brief Obtains the map size. 62 * 63 * In the multithread scenario, the map size returned is a tmp status, 64 * because elements may be inserted or removed by other threads after 65 * <b>Size()</b> is called. 66 */ Size()67 int Size() 68 { 69 std::lock_guard<ffrt::mutex> lock(mutex_); 70 return map_.size(); 71 } 72 73 /** 74 * @brief Checks whether the map is empty. 75 * 76 * In the multithread scenario, the value returned by <b>Empty()</b> is a 77 * tmp status, because elements may be inserted or removed by other threads 78 * after <b>Empty()</b> is called. 79 * 80 * @return Returns <b>true</b> if the map is empty; 81 * returns <b>false</b> otherwise. 82 */ IsEmpty()83 bool IsEmpty() 84 { 85 std::lock_guard<ffrt::mutex> lock(mutex_); 86 return map_.empty(); 87 } 88 89 /** 90 * @brief Inserts an element to the map. 91 * 92 * @param key Indicates the key of the key-value (KV) pair to insert. 93 * @param value Indicates the value of the KV pair to insert. 94 * @return Returns <b>true</b> if the KV pair is inserted; returns 95 * <b>false</b> otherwise. 96 */ Insert(const K & key,const V & value)97 bool Insert(const K& key, const V& value) 98 { 99 std::lock_guard<ffrt::mutex> lock(mutex_); 100 auto ret = map_.insert(std::pair<K, V>(key, value)); 101 return ret.second; 102 } 103 104 /** 105 * @brief Forcibly inserts an element to the map. 106 * 107 * @param key Indicates the key of the KV pair to insert. 108 * @param value Indicates the value of the KV pair to insert. 109 * @note If the key to insert already exists, delete and then insert 110 * the KV pair to ensure that the value is inserted. 111 */ EnsureInsert(const K & key,const V & value)112 void EnsureInsert(const K& key, const V& value) 113 { 114 std::lock_guard<ffrt::mutex> lock(mutex_); 115 auto ret = map_.insert(std::pair<K, V>(key, value)); 116 // find key and cannot insert 117 if (!ret.second) { 118 map_.erase(ret.first); 119 map_.insert(std::pair<K, V>(key, value)); 120 return; 121 } 122 return; 123 } 124 125 /** 126 * @brief Searches for an element in the map. 127 * 128 * @param Key Indicates the key to search. 129 * @param value Indicates the value of the KV pair to search. 130 * @return Returns <b>true</b> if the KV pair is found; 131 * returns <b>false</b> otherwise. 132 */ Find(const K & key,V & value)133 bool Find(const K& key, V& value) 134 { 135 bool ret = false; 136 std::lock_guard<ffrt::mutex> lock(mutex_); 137 138 auto iter = map_.find(key); 139 if (iter != map_.end()) { 140 value = iter->second; 141 ret = true; 142 } 143 144 return ret; 145 } 146 147 /** 148 * @brief Replaces the value of a KV pair. 149 * 150 * @param Key Indicates the key of the KV pair. 151 * @param oldValue Indicates the value to be replaced. 152 * @param newValue Indicates the new value of the KV pair. 153 * @return Returns <b>true</b> if the key is replaced; 154 * returns <b>false</b> otherwise. 155 */ FindOldAndSetNew(const K & key,V & oldValue,const V & newValue)156 bool FindOldAndSetNew(const K& key, V& oldValue, const V& newValue) 157 { 158 bool ret = false; 159 std::lock_guard<ffrt::mutex> lock(mutex_); 160 if (map_.size() > 0) { 161 auto iter = map_.find(key); 162 if (iter != map_.end()) { 163 oldValue = iter->second; 164 map_.erase(iter); 165 map_.insert(std::pair<K, V>(key, newValue)); 166 ret = true; 167 } 168 } 169 170 return ret; 171 } 172 173 /** 174 * @brief Erases a KV pair. 175 * 176 * @param Key Indicates the key of the KV pair to erase. 177 */ Erase(const K & key)178 void Erase(const K& key) 179 { 180 std::lock_guard<ffrt::mutex> lock(mutex_); 181 map_.erase(key); 182 } 183 184 /** 185 * @brief Deletes all KV pairs from the map. 186 */ Clear()187 void Clear() 188 { 189 std::lock_guard<ffrt::mutex> lock(mutex_); 190 map_.clear(); 191 return; 192 } 193 194 using SafeMapCallBack = std::function<void(const K, V&)>; 195 196 /** 197 * @brief Iterates over the elements of the map. 198 * 199 * @param callback Called to perform the custom operations on 200 * each KV pair. 201 */ Iterate(const SafeMapCallBack & callback)202 void Iterate(const SafeMapCallBack& callback) 203 { 204 std::lock_guard<ffrt::mutex> lock(mutex_); 205 if (!map_.empty()) { 206 for (auto it = map_.begin(); it != map_.end(); it++) { 207 callback(it -> first, it -> second); 208 } 209 } 210 } 211 212 private: 213 ffrt::mutex mutex_; 214 std::map<K, V> map_; 215 }; 216 217 } // namespace OHOS 218 #endif // APP_DOMAIN_VERIFY_SAFEMAP_H 219