• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H
17 #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H
18 #include <functional>
19 #include <map>
20 #include <mutex>
21 namespace OHOS {
22 template<typename _Key, typename _Tp>
23 class ConcurrentMap {
24 public:
25     using key_type = typename std::map<_Key, _Tp>::key_type;
26     using mapped_type = typename std::map<_Key, _Tp>::mapped_type;
27     using value_type = typename std::map<_Key, _Tp>::value_type;
28     using size_type = typename std::map<_Key, _Tp>::size_type;
29     using reference = typename std::map<_Key, _Tp>::reference;
30     using const_reference = typename std::map<_Key, _Tp>::const_reference;
31 
32     ConcurrentMap() = default;
~ConcurrentMap()33     ~ConcurrentMap()
34     {
35         Clear();
36     }
37 
ConcurrentMap(const ConcurrentMap & other)38     ConcurrentMap(const ConcurrentMap &other)
39     {
40         operator=(std::move(other));
41     }
42 
43     ConcurrentMap &operator=(const ConcurrentMap &other) noexcept
44     {
45         if (this == &other) {
46             return *this;
47         }
48         auto tmp = other.Clone();
49         std::lock_guard<decltype(mutex_)> lock(mutex_);
50         entries_ = std::move(tmp);
51         return *this;
52     }
53 
ConcurrentMap(ConcurrentMap && other)54     ConcurrentMap(ConcurrentMap &&other) noexcept
55     {
56         operator=(std::move(other));
57     }
58 
59     ConcurrentMap &operator=(ConcurrentMap &&other) noexcept
60     {
61         if (this == &other) {
62             return *this;
63         }
64         auto tmp = other.Steal();
65         std::lock_guard<decltype(mutex_)> lock(mutex_);
66         entries_ = std::move(tmp);
67         return *this;
68     }
69 
70     template<typename... _Args>
Emplace(_Args &&...__args)71     bool Emplace(_Args &&...__args) noexcept
72     {
73         std::lock_guard<decltype(mutex_)> lock(mutex_);
74         auto it = entries_.emplace(std::forward<_Args>(__args)...);
75         return it->second;
76     }
77 
Find(const key_type & key)78     std::pair<bool, mapped_type> Find(const key_type &key) const noexcept
79     {
80         std::lock_guard<decltype(mutex_)> lock(mutex_);
81         auto it = entries_.find(key);
82         if (it == entries_.end()) {
83             return std::pair { false, mapped_type() };
84         }
85 
86         return std::pair { true, it->second };
87     }
88 
Contains(const key_type & key)89     bool Contains(const key_type& key) const noexcept
90     {
91         std::lock_guard<decltype(mutex_)> lock(mutex_);
92         return (entries_.find(key) != entries_.end());
93     }
94 
Insert(const key_type & key,const mapped_type & value)95     bool Insert(const key_type &key, const mapped_type &value) noexcept
96     {
97         std::lock_guard<decltype(mutex_)> lock(mutex_);
98         auto it = entries_.insert(value_type { key, value });
99         return it.second;
100     }
101 
Erase(const key_type & key)102     size_type Erase(const key_type &key) noexcept
103     {
104         std::lock_guard<decltype(mutex_)> lock(mutex_);
105         return entries_.erase(key);
106     }
107 
Clear()108     void Clear() noexcept
109     {
110         std::lock_guard<decltype(mutex_)> lock(mutex_);
111         return entries_.clear();
112     }
113 
Empty()114     bool Empty() const noexcept
115     {
116         std::lock_guard<decltype(mutex_)> lock(mutex_);
117         return entries_.empty();
118     }
119 
Size()120     size_type Size() const noexcept
121     {
122         std::lock_guard<decltype(mutex_)> lock(mutex_);
123         return entries_.size();
124     }
125 
EraseIf(const std::function<bool (const key_type & key,mapped_type & value)> & action)126     size_type EraseIf(const std::function<bool(const key_type &key, mapped_type &value)> &action) noexcept
127     {
128         if (action == nullptr) {
129             return 0;
130         }
131         std::lock_guard<decltype(mutex_)> lock(mutex_);
132 #if __cplusplus > 201703L
133         auto count = std::erase_if(entries_,
134             [&action](value_type &value) -> bool { return action(value.first, value.second); });
135 #else
136         auto count = entries_.size();
137         for (auto it = entries_.begin(); it != entries_.end();) {
138             if (action((*it).first, (*it).second)) {
139                 it = entries_.erase(it);
140             } else {
141                 ++it;
142             }
143         }
144         count -= entries_.size();
145 #endif
146         return count;
147     }
148 
149     mapped_type &operator[](const key_type &key) noexcept
150     {
151         std::lock_guard<decltype(mutex_)> lock(mutex_);
152         return entries_[key];
153     }
154 
ForEach(const std::function<bool (const key_type &,mapped_type &)> & action)155     void ForEach(const std::function<bool(const key_type &, mapped_type &)> &action)
156     {
157         if (action == nullptr) {
158             return;
159         }
160         std::lock_guard<decltype(mutex_)> lock(mutex_);
161         for (auto &[key, value] : entries_) {
162             if (action(key, value)) {
163                 break;
164             }
165         }
166     }
167 
Compute(const key_type & key,const std::function<bool (const key_type &,mapped_type &)> & action)168     bool Compute(const key_type &key, const std::function<bool(const key_type &, mapped_type &)> &action)
169     {
170         if (action == nullptr) {
171             return false;
172         }
173         std::lock_guard<decltype(mutex_)> lock(mutex_);
174         auto it = entries_.find(key);
175         if (it == entries_.end()) {
176             auto result = entries_.emplace(key, mapped_type());
177             it = result.second ? result.first : entries_.end();
178         }
179         if (it == entries_.end()) {
180             return false;
181         }
182         action(it->first, it->second);
183         return true;
184     }
185 
ComputeIfPresent(const key_type & key,const std::function<void (const key_type &,mapped_type &)> & action)186     bool ComputeIfPresent(const key_type &key, const std::function<void(const key_type &, mapped_type &)> &action)
187     {
188         if (action == nullptr) {
189             return false;
190         }
191         std::lock_guard<decltype(mutex_)> lock(mutex_);
192         auto it = entries_.find(key);
193         if (it == entries_.end()) {
194             return false;
195         }
196         action(key, it->second);
197         return true;
198     }
199 
ComputeIfAbsent(const key_type & key,const std::function<mapped_type (const key_type &)> & action)200     bool ComputeIfAbsent(const key_type &key, const std::function<mapped_type(const key_type &)> &action)
201     {
202         if (action == nullptr) {
203             return false;
204         }
205         std::lock_guard<decltype(mutex_)> lock(mutex_);
206         auto it = entries_.find(key);
207         if (it != entries_.end()) {
208             return false;
209         }
210         entries_.insert(value_type{key, action(key)});
211         return true;
212     }
213 private:
Steal()214     std::map<_Key, _Tp> Steal() noexcept
215     {
216         std::lock_guard<decltype(mutex_)> lock(mutex_);
217         return std::move(entries_);
218     }
219 
Clone()220     std::map<_Key, _Tp> Clone() const noexcept
221     {
222         std::lock_guard<decltype(mutex_)> lock(mutex_);
223         return entries_;
224     }
225 private:
226     mutable std::recursive_mutex mutex_;
227     std::map<_Key, _Tp> entries_;
228 };
229 }
230 #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H
231