13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci 163f4cbf05Sopenharmony_ci#ifndef UTILS_BASE_SAFE_MAP_H 173f4cbf05Sopenharmony_ci#define UTILS_BASE_SAFE_MAP_H 183f4cbf05Sopenharmony_ci 193f4cbf05Sopenharmony_ci#include <map> 203f4cbf05Sopenharmony_ci#include <mutex> 213f4cbf05Sopenharmony_ci 223f4cbf05Sopenharmony_cinamespace OHOS { 233f4cbf05Sopenharmony_ci 243f4cbf05Sopenharmony_ci/** 253f4cbf05Sopenharmony_ci * @brief Provides interfaces for thread-safe map operations. 263f4cbf05Sopenharmony_ci */ 273f4cbf05Sopenharmony_citemplate <typename K, typename V> 283f4cbf05Sopenharmony_ciclass SafeMap { 293f4cbf05Sopenharmony_cipublic: 303f4cbf05Sopenharmony_ci SafeMap() {} 313f4cbf05Sopenharmony_ci 323f4cbf05Sopenharmony_ci ~SafeMap() {} 333f4cbf05Sopenharmony_ci 343f4cbf05Sopenharmony_ci SafeMap(const SafeMap& rhs) 353f4cbf05Sopenharmony_ci { 363f4cbf05Sopenharmony_ci operator=(rhs); 373f4cbf05Sopenharmony_ci } 383f4cbf05Sopenharmony_ci 393f4cbf05Sopenharmony_ci SafeMap& operator=(const SafeMap& rhs) 403f4cbf05Sopenharmony_ci { 413f4cbf05Sopenharmony_ci if (this == &rhs) { 423f4cbf05Sopenharmony_ci return *this; 433f4cbf05Sopenharmony_ci } 443f4cbf05Sopenharmony_ci auto tmp = rhs.Clone(); 453f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 463f4cbf05Sopenharmony_ci map_ = std::move(tmp); 473f4cbf05Sopenharmony_ci 483f4cbf05Sopenharmony_ci return *this; 493f4cbf05Sopenharmony_ci } 503f4cbf05Sopenharmony_ci 513f4cbf05Sopenharmony_ci V ReadVal(const K& key) 523f4cbf05Sopenharmony_ci { 533f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 543f4cbf05Sopenharmony_ci return map_[key]; 553f4cbf05Sopenharmony_ci } 563f4cbf05Sopenharmony_ci 573f4cbf05Sopenharmony_ci template<typename LambdaCallback> 583f4cbf05Sopenharmony_ci void ChangeValueByLambda(const K& key, LambdaCallback callback) 593f4cbf05Sopenharmony_ci { 603f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 613f4cbf05Sopenharmony_ci callback(map_[key]); 623f4cbf05Sopenharmony_ci } 633f4cbf05Sopenharmony_ci 643f4cbf05Sopenharmony_ci /** 653f4cbf05Sopenharmony_ci * @brief Obtains the map size. 663f4cbf05Sopenharmony_ci * 673f4cbf05Sopenharmony_ci * In the multithread scenario, the map size returned is a tmp status, 683f4cbf05Sopenharmony_ci * because elements may be inserted or removed by other threads after 693f4cbf05Sopenharmony_ci * <b>Size()</b> is called. 703f4cbf05Sopenharmony_ci */ 713f4cbf05Sopenharmony_ci int Size() 723f4cbf05Sopenharmony_ci { 733f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 743f4cbf05Sopenharmony_ci return map_.size(); 753f4cbf05Sopenharmony_ci } 763f4cbf05Sopenharmony_ci 773f4cbf05Sopenharmony_ci /** 783f4cbf05Sopenharmony_ci * @brief Checks whether the map is empty. 793f4cbf05Sopenharmony_ci * 803f4cbf05Sopenharmony_ci * In the multithread scenario, the value returned by <b>Empty()</b> is a 813f4cbf05Sopenharmony_ci * tmp status, because elements may be inserted or removed by other threads 823f4cbf05Sopenharmony_ci * after <b>Empty()</b> is called. 833f4cbf05Sopenharmony_ci * 843f4cbf05Sopenharmony_ci * @return Returns <b>true</b> if the map is empty; 853f4cbf05Sopenharmony_ci * returns <b>false</b> otherwise. 863f4cbf05Sopenharmony_ci */ 873f4cbf05Sopenharmony_ci bool IsEmpty() 883f4cbf05Sopenharmony_ci { 893f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 903f4cbf05Sopenharmony_ci return map_.empty(); 913f4cbf05Sopenharmony_ci } 923f4cbf05Sopenharmony_ci 933f4cbf05Sopenharmony_ci /** 943f4cbf05Sopenharmony_ci * @brief Inserts an element to the map. 953f4cbf05Sopenharmony_ci * 963f4cbf05Sopenharmony_ci * @param key Indicates the key of the key-value (KV) pair to insert. 973f4cbf05Sopenharmony_ci * @param value Indicates the value of the KV pair to insert. 983f4cbf05Sopenharmony_ci * @return Returns <b>true</b> if the KV pair is inserted; returns 993f4cbf05Sopenharmony_ci * <b>false</b> otherwise. 1003f4cbf05Sopenharmony_ci */ 1013f4cbf05Sopenharmony_ci bool Insert(const K& key, const V& value) 1023f4cbf05Sopenharmony_ci { 1033f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1043f4cbf05Sopenharmony_ci auto ret = map_.insert(std::pair<K, V>(key, value)); 1053f4cbf05Sopenharmony_ci return ret.second; 1063f4cbf05Sopenharmony_ci } 1073f4cbf05Sopenharmony_ci 1083f4cbf05Sopenharmony_ci /** 1093f4cbf05Sopenharmony_ci * @brief Forcibly inserts an element to the map. 1103f4cbf05Sopenharmony_ci * 1113f4cbf05Sopenharmony_ci * @param key Indicates the key of the KV pair to insert. 1123f4cbf05Sopenharmony_ci * @param value Indicates the value of the KV pair to insert. 1133f4cbf05Sopenharmony_ci * @note If the key to insert already exists, delete and then insert 1143f4cbf05Sopenharmony_ci * the KV pair to ensure that the value is inserted. 1153f4cbf05Sopenharmony_ci */ 1163f4cbf05Sopenharmony_ci void EnsureInsert(const K& key, const V& value) 1173f4cbf05Sopenharmony_ci { 1183f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1193f4cbf05Sopenharmony_ci auto ret = map_.insert(std::pair<K, V>(key, value)); 1203f4cbf05Sopenharmony_ci // find key and cannot insert 1213f4cbf05Sopenharmony_ci if (!ret.second) { 1223f4cbf05Sopenharmony_ci map_.erase(ret.first); 1233f4cbf05Sopenharmony_ci map_.insert(std::pair<K, V>(key, value)); 1243f4cbf05Sopenharmony_ci return; 1253f4cbf05Sopenharmony_ci } 1263f4cbf05Sopenharmony_ci return; 1273f4cbf05Sopenharmony_ci } 1283f4cbf05Sopenharmony_ci 1293f4cbf05Sopenharmony_ci /** 1303f4cbf05Sopenharmony_ci * @brief Searches for an element in the map. 1313f4cbf05Sopenharmony_ci * 1323f4cbf05Sopenharmony_ci * @param Key Indicates the key to search. 1333f4cbf05Sopenharmony_ci * @param value Indicates the value of the KV pair to search. 1343f4cbf05Sopenharmony_ci * @return Returns <b>true</b> if the KV pair is found; 1353f4cbf05Sopenharmony_ci * returns <b>false</b> otherwise. 1363f4cbf05Sopenharmony_ci */ 1373f4cbf05Sopenharmony_ci bool Find(const K& key, V& value) 1383f4cbf05Sopenharmony_ci { 1393f4cbf05Sopenharmony_ci bool ret = false; 1403f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1413f4cbf05Sopenharmony_ci 1423f4cbf05Sopenharmony_ci auto iter = map_.find(key); 1433f4cbf05Sopenharmony_ci if (iter != map_.end()) { 1443f4cbf05Sopenharmony_ci value = iter->second; 1453f4cbf05Sopenharmony_ci ret = true; 1463f4cbf05Sopenharmony_ci } 1473f4cbf05Sopenharmony_ci 1483f4cbf05Sopenharmony_ci return ret; 1493f4cbf05Sopenharmony_ci } 1503f4cbf05Sopenharmony_ci 1513f4cbf05Sopenharmony_ci /** 1523f4cbf05Sopenharmony_ci * @brief Replaces the value of a KV pair. 1533f4cbf05Sopenharmony_ci * 1543f4cbf05Sopenharmony_ci * @param Key Indicates the key of the KV pair. 1553f4cbf05Sopenharmony_ci * @param oldValue Indicates the value to be replaced. 1563f4cbf05Sopenharmony_ci * @param newValue Indicates the new value of the KV pair. 1573f4cbf05Sopenharmony_ci * @return Returns <b>true</b> if the key is replaced; 1583f4cbf05Sopenharmony_ci * returns <b>false</b> otherwise. 1593f4cbf05Sopenharmony_ci */ 1603f4cbf05Sopenharmony_ci bool FindOldAndSetNew(const K& key, V& oldValue, const V& newValue) 1613f4cbf05Sopenharmony_ci { 1623f4cbf05Sopenharmony_ci bool ret = false; 1633f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1643f4cbf05Sopenharmony_ci if (map_.size() > 0) { 1653f4cbf05Sopenharmony_ci auto iter = map_.find(key); 1663f4cbf05Sopenharmony_ci if (iter != map_.end()) { 1673f4cbf05Sopenharmony_ci oldValue = iter->second; 1683f4cbf05Sopenharmony_ci map_.erase(iter); 1693f4cbf05Sopenharmony_ci map_.insert(std::pair<K, V>(key, newValue)); 1703f4cbf05Sopenharmony_ci ret = true; 1713f4cbf05Sopenharmony_ci } 1723f4cbf05Sopenharmony_ci } 1733f4cbf05Sopenharmony_ci 1743f4cbf05Sopenharmony_ci return ret; 1753f4cbf05Sopenharmony_ci } 1763f4cbf05Sopenharmony_ci 1773f4cbf05Sopenharmony_ci /** 1783f4cbf05Sopenharmony_ci * @brief Erases a KV pair. 1793f4cbf05Sopenharmony_ci * 1803f4cbf05Sopenharmony_ci * @param Key Indicates the key of the KV pair to erase. 1813f4cbf05Sopenharmony_ci */ 1823f4cbf05Sopenharmony_ci void Erase(const K& key) 1833f4cbf05Sopenharmony_ci { 1843f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1853f4cbf05Sopenharmony_ci map_.erase(key); 1863f4cbf05Sopenharmony_ci } 1873f4cbf05Sopenharmony_ci 1883f4cbf05Sopenharmony_ci /** 1893f4cbf05Sopenharmony_ci * @brief Deletes all KV pairs from the map. 1903f4cbf05Sopenharmony_ci */ 1913f4cbf05Sopenharmony_ci void Clear() 1923f4cbf05Sopenharmony_ci { 1933f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 1943f4cbf05Sopenharmony_ci map_.clear(); 1953f4cbf05Sopenharmony_ci return; 1963f4cbf05Sopenharmony_ci } 1973f4cbf05Sopenharmony_ci 1983f4cbf05Sopenharmony_ci using SafeMapCallBack = std::function<void(const K, V&)>; 1993f4cbf05Sopenharmony_ci 2003f4cbf05Sopenharmony_ci /** 2013f4cbf05Sopenharmony_ci * @brief Iterates over the elements of the map. 2023f4cbf05Sopenharmony_ci * 2033f4cbf05Sopenharmony_ci * @param callback Called to perform the custom operations on 2043f4cbf05Sopenharmony_ci * each KV pair. 2053f4cbf05Sopenharmony_ci */ 2063f4cbf05Sopenharmony_ci void Iterate(const SafeMapCallBack& callback) 2073f4cbf05Sopenharmony_ci { 2083f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 2093f4cbf05Sopenharmony_ci if (!map_.empty()) { 2103f4cbf05Sopenharmony_ci for (auto it = map_.begin(); it != map_.end(); it++) { 2113f4cbf05Sopenharmony_ci callback(it -> first, it -> second); 2123f4cbf05Sopenharmony_ci } 2133f4cbf05Sopenharmony_ci } 2143f4cbf05Sopenharmony_ci } 2153f4cbf05Sopenharmony_ci 2163f4cbf05Sopenharmony_ciprivate: 2173f4cbf05Sopenharmony_ci mutable std::mutex mutex_; 2183f4cbf05Sopenharmony_ci std::map<K, V> map_; 2193f4cbf05Sopenharmony_ci 2203f4cbf05Sopenharmony_ci std::map<K, V> Clone() const noexcept 2213f4cbf05Sopenharmony_ci { 2223f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 2233f4cbf05Sopenharmony_ci return map_; 2243f4cbf05Sopenharmony_ci } 2253f4cbf05Sopenharmony_ci}; 2263f4cbf05Sopenharmony_ci 2273f4cbf05Sopenharmony_ci} // namespace OHOS 2283f4cbf05Sopenharmony_ci#endif 229