Reputation: 1495
Say we have a data structure protected by a lock.
Now, Thread1 carries out these statements(say in function block X):
mGeoCodeVectorLock.lock();
auto it = std::find(mGeoCodeVector.begin(), mGeoCodeVector.end(), tokenName);
if(it != mGeoCodeVector.end()) {
mGeoCodeVector.erase(it);
}
mGeoCodeVectorLock.unlock();
And then Thread2 executes these statements(say in another function block Y):
auto iter = std::find(mGeoCodeVector.begin(), mGeoCodeVector.end(), tokenName);
mGeoCodeVectorLock.lock();
if(it != mGeoCodeVector.end()) {
mGeoCodeVector.erase(it);
}
mGeoCodeVectorLock.unlock();
Now, The way I see it:
1) If thread1 gets the lock in function block X and manages to erase the vector, then , the thread already holding an iterator and waiting on lock in function block Y ends up with an invalidated iterator since the container size has been changed by thread1.
2) So, the easy way to fix it would be i guess, to take all your iterators only once you manage to get hold of lock.
Are there some general principles/idioms of safe iterator usage, especially with regards to multi threaded applications?
Upvotes: 0
Views: 287
Reputation: 62563
What is your structure, is it a true vector or a list? If it is a vector, you have to aquire the lock before doing find. However, if it is a list (or can be made a list) removing from the list doesn't invalidate any iterators other than to the object being removed, so as long as token name is different, no locks are required.
Upvotes: 0
Reputation: 69864
Yes.
of course, using RAII in the implementation of the lock automates 1 and 5.
Upvotes: 4