• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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