I have multiple threads modifying an stl vector and an stl list.
I want to avoid having to take a lock if the container is empty
Would the following code be threadsafe? What if items was a list or a map?
class A
{
vector<int> items
void DoStuff()
{
if(!items.empty())
{
AquireLock();
DoStuffWithItems();
ReleaseLock();
}
}
}
It depends what you expect. The other answers are right that in general, standard C++ containers are not thread-safe, and furthermore, that in particular your code doesn’t ward against another thread modifying the container between your call to
emptyand the acquisition of the lock (but this matter is unrelated to the thread safety ofvector::empty).So, to ward off any misunderstandings: Your code does not guarantee
itemswill be non-empty inside the block.But your code can still be useful, since all you want to do is avoid redundant lock creations. Your code doesn’t give guarantees but it may prevent an unnecessary lock creation. It won’t work in all cases (other threads can still empty the container between your check and the lock) but in some cases. And if all you’re after is an optimization by omitting a redundant lock, then your code accomplishes that goal.
Just make sure that any actual access to the container is protected by locks.
By the way, the above is strictly speaking undefined behaviour: an STL implementation is theoretically allowed to modify
mutablemembers inside the call toempty. This would mean that the apparently harmless (because read-only) call toemptycan actually cause a conflict. Unfortunately, you cannot rely on the assumption that read-only calls are safe with STL containers.In practice, though, I am pretty sure that
vector::emptywill not modify any members. But already forlist::emptyI am less sure. If you really want guarantees, then either lock every access or don’t use the STL containers.