basav
basav

Reputation: 1495

safe usage of iterators in multithreaded applications

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

Answers (2)

SergeyA
SergeyA

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

Richard Hodges
Richard Hodges

Reputation: 69864

Yes.

  1. Lock the resource
  2. create the iterators
  3. mutate or query the resource
  4. throw away the iterators
  5. unlock the resource.

of course, using RAII in the implementation of the lock automates 1 and 5.

Upvotes: 4

Related Questions