1 | /** |
2 | * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | |
16 | * \author Haichao.chc |
17 | * \date Oct 2020 |
18 | * \brief Concurrent hashmap which is thread-safe for add/del operations |
19 | */ |
20 | |
21 | #pragma once |
22 | |
23 | #include <unordered_map> |
24 | #include <ailego/parallel/lock.h> |
25 | |
26 | namespace proxima { |
27 | namespace be { |
28 | namespace index { |
29 | |
30 | /* |
31 | * Concurrent hash map for synchronously get/set item. |
32 | */ |
33 | template <typename TKey, typename TValue> |
34 | class ConcurrentHashMap { |
35 | public: |
36 | //! Constructor |
37 | ConcurrentHashMap() = default; |
38 | |
39 | //! Destructor |
40 | ~ConcurrentHashMap() = default; |
41 | |
42 | public: |
43 | //! Emplace a key-value pair |
44 | void emplace(TKey key, TValue val) { |
45 | rw_lock_.lock(); |
46 | map_.emplace(key, val); |
47 | rw_lock_.unlock(); |
48 | } |
49 | |
50 | //! Get value by key |
51 | const TValue &get(TKey key) const { |
52 | rw_lock_.lock_shared(); |
53 | const TValue &val = map_.at(key); |
54 | rw_lock_.unlock_shared(); |
55 | return val; |
56 | } |
57 | |
58 | //! If has key |
59 | bool has(TKey key) const { |
60 | bool found = false; |
61 | rw_lock_.lock_shared(); |
62 | if (map_.find(key) != map_.end()) { |
63 | found = true; |
64 | } |
65 | rw_lock_.unlock_shared(); |
66 | return found; |
67 | } |
68 | |
69 | //! Return key-value pair count |
70 | size_t size() const { |
71 | size_t val; |
72 | rw_lock_.lock_shared(); |
73 | val = map_.size(); |
74 | rw_lock_.unlock_shared(); |
75 | return val; |
76 | } |
77 | |
78 | //! Erase a pair by key |
79 | void erase(TKey key) { |
80 | rw_lock_.lock(); |
81 | map_.erase(key); |
82 | rw_lock_.unlock(); |
83 | } |
84 | |
85 | //! Clear all pairs |
86 | void clear() { |
87 | rw_lock_.lock(); |
88 | map_.clear(); |
89 | rw_lock_.unlock(); |
90 | } |
91 | |
92 | typedef typename std::unordered_map<TKey, TValue>::iterator iterator; |
93 | typedef |
94 | typename std::unordered_map<TKey, TValue>::const_iterator const_iterator; |
95 | |
96 | // NOTICE: iterator interface is only called when |
97 | // uppper class destruct, and ensure in single thread |
98 | // |
99 | // Return begin iterator |
100 | iterator begin() { |
101 | rw_lock_.lock_shared(); |
102 | iterator it = map_.begin(); |
103 | rw_lock_.unlock_shared(); |
104 | return it; |
105 | } |
106 | |
107 | //! Return const begin iterator |
108 | const_iterator begin() const { |
109 | rw_lock_.lock_shared(); |
110 | const_iterator it = map_.begin(); |
111 | rw_lock_.unlock_shared(); |
112 | return it; |
113 | } |
114 | |
115 | //! Return reverse begin iterator |
116 | const_iterator cbegin() const { |
117 | rw_lock_.lock_shared(); |
118 | const_iterator it = map_.cbegin(); |
119 | rw_lock_.unlock_shared(); |
120 | return it; |
121 | } |
122 | |
123 | //! Return end iterator |
124 | iterator end() { |
125 | rw_lock_.lock_shared(); |
126 | iterator it = map_.end(); |
127 | rw_lock_.unlock_shared(); |
128 | return it; |
129 | } |
130 | |
131 | //! Return const end iterator |
132 | const_iterator end() const { |
133 | rw_lock_.lock_shared(); |
134 | const_iterator it = map_.end(); |
135 | rw_lock_.unlock_shared(); |
136 | return it; |
137 | } |
138 | |
139 | //! Return cend iterator |
140 | const_iterator cend() const { |
141 | rw_lock_.lock_shared(); |
142 | const_iterator it = map_.cend(); |
143 | rw_lock_.unlock_shared(); |
144 | return it; |
145 | } |
146 | |
147 | private: |
148 | mutable ailego::SharedMutex rw_lock_{}; |
149 | std::unordered_map<TKey, TValue> map_{}; |
150 | }; |
151 | |
152 | |
153 | } // end namespace index |
154 | } // namespace be |
155 | } // end namespace proxima |
156 | |