@@ -39,93 +39,108 @@ namespace backend {
3939
4040InMemoryPerProcess::InMemoryPerProcess (const std::string &name) :
4141 Collection (name) {
42- this ->reserve (1000 );
43- pthread_mutex_init (&m_lock, NULL );
42+ m_map.reserve (1000 );
4443}
4544
4645InMemoryPerProcess::~InMemoryPerProcess () {
47- this ->clear ();
48- pthread_mutex_destroy (&m_lock);
46+ m_map.clear ();
4947}
5048
51- void InMemoryPerProcess::store (std::string key, std::string value) {
52- pthread_mutex_lock (&m_lock);
53- this ->emplace (key, value);
54- pthread_mutex_unlock (&m_lock);
55- }
5649
50+ template <typename Map>
51+ inline void __store (Map &map, std::string key, std::string value) {
52+ // NOTE: should be called with write-lock previously acquired
5753
58- bool InMemoryPerProcess::storeOrUpdateFirst (const std::string &key,
59- const std::string &value) {
60- if (updateFirst (key, value) == false ) {
61- store (key, value);
62- }
63- return true ;
54+ map.emplace (key, value);
6455}
6556
6657
67- bool InMemoryPerProcess::updateFirst (const std::string &key,
58+ template <typename Map>
59+ inline bool __updateFirst (Map &map,
60+ const std::string &key,
6861 const std::string &value) {
69- pthread_mutex_lock (&m_lock);
62+ // NOTE: should be called with write-lock previously acquired
7063
71- if (auto search = this -> find (key); search != this -> end ()) {
64+ if (auto search = map. find (key); search != map. end ()) {
7265 search->second .setValue (value);
73- pthread_mutex_unlock (&m_lock);
7466 return true ;
7567 }
7668
77- pthread_mutex_unlock (&m_lock);
7869 return false ;
7970}
8071
8172
73+ void InMemoryPerProcess::store (const std::string &key, const std::string &value) {
74+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
75+ __store (m_map, key, value);
76+ }
77+
78+
79+ bool InMemoryPerProcess::storeOrUpdateFirst (const std::string &key,
80+ const std::string &value) {
81+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
82+ if (__updateFirst (m_map, key, value) == false ) {
83+ __store (m_map, key, value);
84+ }
85+ return true ;
86+ }
87+
88+
89+ bool InMemoryPerProcess::updateFirst (const std::string &key,
90+ const std::string &value) {
91+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
92+ return __updateFirst (m_map, key, value);
93+ }
94+
95+
8296void InMemoryPerProcess::del (const std::string& key) {
83- pthread_mutex_lock (&m_lock);
84- this ->erase (key);
85- pthread_mutex_unlock (&m_lock);
97+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
98+ m_map.erase (key);
8699}
87100
88101void InMemoryPerProcess::delIfExpired (const std::string& key) {
89- pthread_mutex_lock (&m_lock);
102+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
90103 // Double check the status while within the mutex
91- auto iter = this ->find (key);
92- if ((iter != this ->end ()) && (iter->second .isExpired ())) {
93- this ->erase (key);
104+ const auto iter = std::find_if (m_map.begin (), m_map.end (),
105+ [&key](const auto &x) { return x.first == key && x.second .isExpired (); });
106+ if (iter != m_map.end ()) {
107+ m_map.erase (key);
94108 }
95- pthread_mutex_unlock (&m_lock);
96109}
97110
98111void InMemoryPerProcess::setExpiry (const std::string& key, int32_t expiry_seconds) {
99- pthread_mutex_lock (&m_lock);
112+ const std::lock_guard lock (m_mutex); // write lock (exclusive access)
100113
101- if (auto search = this -> find (key); search != this -> end ()) {
114+ if (const auto search = m_map. find (key); search != m_map. end ()) {
102115 search->second .setExpiry (expiry_seconds);
103- pthread_mutex_unlock (&m_lock);
104116 return ;
105117 }
106118
107119 // We allow an expiry value to be set for a key that has not (yet) had a value set.
108- auto iter = this -> emplace (key, CollectionData ());
120+ const auto iter = m_map. emplace (key, CollectionData ());
109121 iter->second .setExpiry (expiry_seconds);
110-
111- pthread_mutex_unlock (&m_lock);
112122}
113123
114124
115125void InMemoryPerProcess::resolveSingleMatch (const std::string& var,
116126 std::vector<const VariableValue *> *l) {
117127 std::list<std::string> expiredVars;
118- auto range = this ->equal_range (var);
119-
120- for (auto it = range.first ; it != range.second ; ++it) {
121- if (it->second .isExpired ()) {
122- expiredVars.push_back (it->first );
123- } else if (it->second .hasValue () == false ) {
124- // No-op. A non-expired expiry exists for the key but there is no actual value
125- } else {
126- l->push_back (new VariableValue (&m_name, &it->first , &it->second .getValue ()));
127- }
128+
129+ {
130+ const std::shared_lock lock (m_mutex); // read lock (shared access)
131+
132+ const auto range = m_map.equal_range (var);
133+ for (auto it = range.first ; it != range.second ; ++it) {
134+ if (it->second .isExpired ()) {
135+ expiredVars.push_back (it->first );
136+ } else if (it->second .hasValue () == false ) {
137+ // No-op. A non-expired expiry exists for the key but there is no actual value
138+ } else {
139+ l->push_back (new VariableValue (&m_name, &it->first , &it->second .getValue ()));
140+ }
141+ }
128142 }
143+
129144 for (const auto & expiredVar : expiredVars) {
130145 delIfExpired (expiredVar);
131146 }
@@ -134,40 +149,45 @@ void InMemoryPerProcess::resolveSingleMatch(const std::string& var,
134149
135150void InMemoryPerProcess::resolveMultiMatches (const std::string& var,
136151 std::vector<const VariableValue *> *l, variables::KeyExclusions &ke) {
137- size_t keySize = var.size ();
152+ const auto keySize = var.size ();
138153 l->reserve (15 );
139154 std::list<std::string> expiredVars;
140155
141- if (keySize == 0 ) {
142- for (auto &i : *this ) {
143- if (ke.toOmit (i.first )) {
144- continue ;
156+ {
157+ const std::shared_lock lock (m_mutex); // read lock (shared access)
158+
159+ if (keySize == 0 ) {
160+ for (auto &i : m_map) {
161+ if (ke.toOmit (i.first )) {
162+ continue ;
163+ }
164+ if (i.second .isExpired ()) {
165+ expiredVars.push_back (i.first );
166+ } else if (i.second .hasValue () == false ) {
167+ // No-op. A non-expired expiry exists for the key but there is no actual value
168+ } else {
169+ l->insert (l->begin (), new VariableValue (&m_name, &i.first ,
170+ &i.second .getValue ()));
171+ }
145172 }
146- if (i. second . isExpired ()) {
147- expiredVars. push_back (i. first );
148- } else if (i. second . hasValue () == false ) {
149- // No-op. A non-expired expiry exists for the key but there is no actual value
150- } else {
151- l-> insert (l-> begin (), new VariableValue (&m_name, &i. first ,
152- &i. second .getValue ()));
153- }
154- }
155- } else {
156- auto range = this -> equal_range (var);
157- for ( auto it = range. first ; it != range. second ; ++it) {
158- if (ke. toOmit (var)) {
159- continue ;
173+ } else {
174+ const auto range = m_map. equal_range (var );
175+ for ( auto it = range. first ; it != range. second ; ++it ) {
176+ if (ke. toOmit (var)) {
177+ continue ;
178+ }
179+ if (it-> second .isExpired ()) {
180+ expiredVars. push_back (it-> first );
181+ } else if (it-> second . hasValue () == false ) {
182+ // No-op. A non-expired expiry exists for the key but there is no actual value
183+ } else {
184+ l-> insert (l-> begin (), new VariableValue (&m_name, &var,
185+ &it-> second . getValue ()));
186+ }
160187 }
161- if (it->second .isExpired ()) {
162- expiredVars.push_back (it->first );
163- } else if (it->second .hasValue () == false ) {
164- // No-op. A non-expired expiry exists for the key but there is no actual value
165- } else {
166- l->insert (l->begin (), new VariableValue (&m_name, &var,
167- &it->second .getValue ()));
168- }
169188 }
170189 }
190+
171191 for (const auto & expiredVar : expiredVars) {
172192 delIfExpired (expiredVar);
173193 }
@@ -176,47 +196,30 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var,
176196
177197void InMemoryPerProcess::resolveRegularExpression (const std::string& var,
178198 std::vector<const VariableValue *> *l, variables::KeyExclusions &ke) {
179-
180- // if (var.find(":") == std::string::npos) {
181- // return;
182- // }
183- // if (var.size() < var.find(":") + 3) {
184- // return;
185- // }
186- // std::string col = std::string(var, 0, var.find(":"));
187- // std::string name = std::string(var, var.find(":") + 2,
188- // var.size() - var.find(":") - 3);
189- // size_t keySize = col.size();
190199 Utils::Regex r (var, true );
191200 std::list<std::string> expiredVars;
192201
193- for ( const auto & x : * this ) {
194- // if (x.first.size() <= keySize + 1) {
195- // continue;
196- // }
197- // if (x.first.at(keySize) != ':') {
198- // continue;
199- // }
200- // if (std::string(x.first, 0, keySize) != col) {
201- // continue;
202- // }
203- // std::string content = std::string(x.first, keySize + 1,
204- // x.first.size() - keySize - 1);
205- int ret = Utils::regex_search (x.first , r );
206- if (ret <= 0 ) {
207- continue ;
208- }
209- if (ke. toOmit ( x.first )) {
210- continue ;
202+ {
203+ const std::shared_lock lock (m_mutex); // read lock (shared access)
204+
205+ for ( const auto & x : m_map) {
206+ const auto ret = Utils::regex_search (x.first , r);
207+ if (ret <= 0 ) {
208+ continue ;
209+ }
210+ if (ke. toOmit (x. first )) {
211+ continue ;
212+ }
213+ if (x. second . isExpired ()) {
214+ expiredVars. push_back (x.first );
215+ } else if (x. second . hasValue () == false ) {
216+ // No-op. A non-expired expiry exists for the key but there is no actual value
217+ } else {
218+ l-> insert (l-> begin (), new VariableValue (&m_name, & x.first , &x. second . getValue ()));
219+ }
211220 }
212- if (x.second .isExpired ()) {
213- expiredVars.push_back (x.first );
214- } else if (x.second .hasValue () == false ) {
215- // No-op. A non-expired expiry exists for the key but there is no actual value
216- } else {
217- l->insert (l->begin (), new VariableValue (&m_name, &x.first , &x.second .getValue ()));
218- }
219221 }
222+
220223 for (const auto & expiredVar : expiredVars) {
221224 delIfExpired (expiredVar);
222225 }
@@ -225,18 +228,29 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var,
225228
226229std::unique_ptr<std::string> InMemoryPerProcess::resolveFirst (
227230 const std::string& var) {
228- auto range = equal_range (var);
229- for (auto it = range.first ; it != range.second ; ++it) {
230- if (it->second .isExpired ()) {
231- delIfExpired (it->second .getValue ());
232- } else if (it->second .hasValue () == false ) {
233- // No-op. A non-expired expiry exists for the key but there is no actual value
234- } else {
235- return std::unique_ptr<std::string>(new std::string (it->second .getValue ()));
236- }
231+ std::unique_ptr<std::string> ret;
232+ std::list<std::string> expiredVars;
233+
234+ {
235+ const std::shared_lock lock (m_mutex); // read lock (shared access)
236+
237+ const auto range = m_map.equal_range (var);
238+ for (auto it = range.first ; it != range.second ; ++it) {
239+ if (it->second .isExpired ()) {
240+ expiredVars.push_back (it->first );
241+ } else if (it->second .hasValue () == false ) {
242+ // No-op. A non-expired expiry exists for the key but there is no actual value
243+ } else {
244+ ret = std::make_unique<std::string>(it->second .getValue ());
245+ }
246+ }
247+ }
248+
249+ for (const auto & expiredVar : expiredVars) {
250+ delIfExpired (expiredVar);
237251 }
238252
239- return NULL ;
253+ return ret ;
240254}
241255
242256
0 commit comments