Skip to content

Commit e1a8af8

Browse files
author
Sebastiano Merlino
committed
Solved concurrency problems with cache
1 parent e9b7659 commit e1a8af8

File tree

1 file changed

+48
-34
lines changed

1 file changed

+48
-34
lines changed

src/webserver.cpp

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -156,24 +156,31 @@ struct cache_entry
156156
int validity;
157157
details::http_response_ptr response;
158158
pthread_rwlock_t elem_guard;
159+
pthread_mutex_t lock_guard;
160+
bool locked;
159161

160162
cache_entry():
161163
ts(-1),
162-
validity(-1)
164+
validity(-1),
165+
locked(false)
163166
{
164167
pthread_rwlock_init(&elem_guard, NULL);
168+
pthread_mutex_init(&lock_guard, NULL);
165169
}
166170

167171
~cache_entry()
168172
{
169173
pthread_rwlock_destroy(&elem_guard);
174+
pthread_mutex_destroy(&lock_guard);
170175
}
171176

172177
cache_entry(const cache_entry& b):
173178
ts(b.ts),
174179
validity(b.validity),
175180
response(b.response),
176-
elem_guard(b.elem_guard)
181+
elem_guard(b.elem_guard),
182+
lock_guard(b.lock_guard),
183+
locked(b.locked)
177184
{
178185
}
179186

@@ -183,15 +190,44 @@ struct cache_entry
183190
validity = b.validity;
184191
response = b.response;
185192
pthread_rwlock_destroy(&elem_guard);
193+
pthread_mutex_destroy(&lock_guard);
186194
elem_guard = b.elem_guard;
195+
locked = b.locked;
187196
}
188197

189198
cache_entry(details::http_response_ptr response, long ts = -1, int validity = -1):
190199
ts(ts),
191200
validity(validity),
192-
response(response)
201+
response(response),
202+
locked(false)
193203
{
194204
pthread_rwlock_init(&elem_guard, NULL);
205+
pthread_mutex_init(&lock_guard, NULL);
206+
}
207+
208+
void lock(bool write = false)
209+
{
210+
pthread_mutex_lock(&lock_guard);
211+
if(!locked)
212+
{
213+
if(write)
214+
pthread_rwlock_wrlock(&elem_guard);
215+
else
216+
pthread_rwlock_rdlock(&elem_guard);
217+
locked = true;
218+
}
219+
pthread_mutex_unlock(&lock_guard);
220+
}
221+
222+
void unlock()
223+
{
224+
pthread_mutex_lock(&lock_guard);
225+
if(locked)
226+
{
227+
pthread_rwlock_unlock(&elem_guard);
228+
locked = false;
229+
}
230+
pthread_mutex_unlock(&lock_guard);
195231
}
196232
};
197233

@@ -200,7 +236,7 @@ namespace details
200236

201237
void unlock_cache_entry(cache_entry* ce)
202238
{
203-
pthread_rwlock_unlock(&ce->elem_guard);
239+
ce->unlock();
204240
}
205241

206242
http_response* get_response(cache_entry* ce)
@@ -1518,12 +1554,7 @@ http_response* webserver::get_from_cache(const std::string& key, bool* valid, ca
15181554
if(it != cache_m->response_cache.end())
15191555
{
15201556
if(lock)
1521-
{
1522-
if(write)
1523-
pthread_rwlock_wrlock(&((*it).second.elem_guard));
1524-
else
1525-
pthread_rwlock_rdlock(&((*it).second.elem_guard));
1526-
}
1557+
(*it).second.lock(write);
15271558
if((*it).second.validity != -1)
15281559
{
15291560
timeval now;
@@ -1574,12 +1605,7 @@ void webserver::lock_cache_element(const std::string& key, bool write)
15741605
pthread_rwlock_rdlock(&cache_guard);
15751606
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15761607
if(it != cache_m->response_cache.end())
1577-
{
1578-
if(write)
1579-
pthread_rwlock_wrlock(&((*it).second.elem_guard));
1580-
else
1581-
pthread_rwlock_rdlock(&((*it).second.elem_guard));
1582-
}
1608+
(*it).second.lock(write);
15831609
pthread_rwlock_unlock(&cache_guard);
15841610
}
15851611

@@ -1588,32 +1614,25 @@ void webserver::unlock_cache_element(const std::string& key)
15881614
pthread_rwlock_rdlock(&cache_guard);
15891615
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15901616
if(it != cache_m->response_cache.end())
1591-
pthread_rwlock_unlock(&((*it).second.elem_guard));
1617+
(*it).second.unlock();
15921618
pthread_rwlock_unlock(&cache_guard);
15931619
}
15941620

15951621
cache_entry* webserver::put_in_cache(const std::string& key, http_response* value, bool* new_elem, bool lock, bool write, int validity)
15961622
{
15971623
pthread_rwlock_wrlock(&cache_guard);
15981624
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
1599-
bool unlock = false;
16001625
cache_entry* to_ret;
1626+
bool unlock = false;
16011627
if(it != cache_m->response_cache.end())
16021628
{
1603-
pthread_rwlock_wrlock(&((*it).second.elem_guard));
1629+
(*it).second.lock(true);
16041630
unlock = true;
16051631
}
16061632
if(validity == -1)
16071633
{
16081634
pair<map<string, cache_entry>::iterator, bool> res = cache_m->response_cache.insert(pair<string, cache_entry>(key, cache_entry(value)));
16091635
to_ret = &((*res.first).second);
1610-
if(lock)
1611-
{
1612-
if(write)
1613-
pthread_rwlock_wrlock(&to_ret->elem_guard);
1614-
else
1615-
pthread_rwlock_rdlock(&to_ret->elem_guard);
1616-
}
16171636
*new_elem = res.second;
16181637
}
16191638
else
@@ -1622,17 +1641,12 @@ cache_entry* webserver::put_in_cache(const std::string& key, http_response* valu
16221641
gettimeofday(&now, NULL);
16231642
pair<map<string, cache_entry>::iterator, bool> res = cache_m->response_cache.insert(pair<string, cache_entry>(key, cache_entry(value, now.tv_sec, validity)));
16241643
to_ret = &((*res.first).second);
1625-
if(lock)
1626-
{
1627-
if(write)
1628-
pthread_rwlock_wrlock(&to_ret->elem_guard);
1629-
else
1630-
pthread_rwlock_rdlock(&to_ret->elem_guard);
1631-
}
16321644
*new_elem = res.second;
16331645
}
16341646
if(unlock)
1635-
pthread_rwlock_unlock(&((*it).second.elem_guard));
1647+
(*it).second.unlock();
1648+
if(lock)
1649+
to_ret->lock(write);
16361650
pthread_rwlock_unlock(&cache_guard);
16371651
return to_ret;
16381652
}

0 commit comments

Comments
 (0)