hoppla
hoppla

Reputation: 51

C++ STL map/vector of vectors and thread safety

I was wondering whether following code would be considered thread-safe. I think it should be, but am not too familiar with what goes on under the hood.

Basically, I have this function in class Foo that will be called on the main thread and takes a vector as an anrgument, ie,

void Foo::func( vector<int> v)

In Foo, I also have a private member,

vector< vector<int> > vecOfVec;

Within func, I'll simply push back any new v onto vecOfVec and check for v 's size. If v is smaller than its expected size, I'd like to kick off another thread that fills up v with some known, predetermined values, like so

void Foo::func( vector<int> v)
{
    int size = v.size();
    int index = vecOfVec.size();

    vecOfVec.push_back(v);

    if (size < 1000)
    {
        boost::thread t( boost::bind( &Foo::PushBackZeros, this, vecOfVec, index) );
    }
}

Foo::PushBackZeros would, as its name suggests simply fill up the vector at 'vecOfVec[index]' with zeros until its size grows to 1000;

Now, I don't see any concurrent read or write operations here on any of the elements of vecOfVec. Obviously, there is a chance of concurrent operations on the entire object, but there will never be concurrencies on a particular element of vecOfVec.

Could someone explain as to whether the above would be considered thread-safe? Would the same extent to STL maps also? If not, please explain. Cheers!

Upvotes: 3

Views: 2185

Answers (3)

CashCow
CashCow

Reputation: 31445

vecOfVec is being passed by value because boost::bind requires you to put a boost::ref around a reference parameter.

So likely thread-safe but not doing what you think it is.

I am not sure why you need to pass that parameter in, as it is already in "this".

To answer the original question though for what you want to do:

  • If vecOfVecs may be resized then any of its members could be invalidated so it would not be thread-safe.
  • Pushing members into one of the inner vectors will not invalidate any other member vectors, so you could have different threads populating different vector members at the same time as long as they are all already there.
  • If you "reserve" ahead then you can push_back more members into your vector until that capacity is reached and it won't invalidate existing members.

Upvotes: 0

tibur
tibur

Reputation: 11636

If your Foo::PushBackZeros has the same signature as Foo::func( vector<int> v), then it will be thread safe, since you pass a copy of the array to that function. So there will be no concurrent access.

Upvotes: 0

Dirk
Dirk

Reputation: 31061

I think, that this is not thread-safe. What happens, if one thread pushes a new element onto the vector, which causes the vector's internal memory area to need to grow? The pushing thread might exchange the memory for a larger buffer, which can cause threads reading in parallel to this operation to suddenly read from invalid(ated) memory. Or threads seeing random values in certain slots, just because they read concurrently to the code which copies the contents of the vector from the old memory location to the new one.

Upvotes: 8

Related Questions