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