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