Consider a thread-safe getter method in its,relatively, simplest form:
std::map<std::string, boost::shared_ptr<AAA> > repo;
AAA & get(const std::string &key)
{
boost::upgrade_lock<boost::shared_mutex> lock(repoMutex);
std::map<std::string, boost::shared_ptr<AAA> >::iterator it = repo.find(key);
if(it == repo.end()){
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
boost::shared_ptr<AAA> t(new AAA(key));
repo.insert(std::make_pair(key,t));
return *t;
}
return *it->second;
}
in above, I use a shared(upgradeable) lock to protect a find operation, and upgrade to unique lock only if I need to insert a key/value. So far so good?
What I imagine is the following(please let me know if in any step my concept is wrong):
Two threads enter the method
Both are allowed to run
repo.find()
for the same key at the same time(and the key doesn't exist).Both of them fail.as the key doesn't exist .
first thread gets exclusive access by entering the upgraded area, while the second thread waiting to enter upgraded area.
first thread finishes its job of creating a new entry for key and then walks off.
second thread enters and overwrites the key/value inserted by the first thread.(which is not what anybody wants)
How do we solve this issue? thanks