Reputation: 909
I'm working on software where multiple threads read-access a single std::vector
with a lot (and large) data.
I have some basic understanding of the complexities of multiple theads accessing a single object and things can be greatly simplified by using a mutex.
In my case, modifying an existing object is a lot more expensive that copying it. So I was thinking about creating a copy, modifing the copy (while not holding the mutex) and then swapping it back into the shared object.
I cannot use C++11, so I don't have access to move operations, but it is my understanding that gcc
uses a very efficient std::vector::swap()
that is comparable with move operations (in terms of speed).
I was thinking about something like this:
pthread_mutex_t mtx;
class bigdata_t { ... };
std::vector<bigdata_t> shared_vec; // accessed by multiple threads
void modify_bigdata()
{
pthread_mutex_lock(&mtx);
std::vector<bigdata_t> tmp_vec = shared_vec; // create copy
pthread_mutex_unlock(&mtx);
/*
* Here, apply expensive modifications to tmp_vec
*/
pthread_mutex_lock(&mtx);
shared_vec.swap(tmp_vec); // this is very fast and does not copy data
pthread_mutex_unlock(&mtx);
}
modify_bigdata()
is only called by a single thread, so this is basically a single writer/multiple reader approach.
It runs very fast, but swapping data back into the shared vector kind of feels like cheating.
My question is:
Is this approach correct and thread-safe ?
Upvotes: 0
Views: 1159
Reputation: 2624
Assuming that you swap the whole vector, it is very dangerous if any reader thread has reference inside that vector as when swapping, it is very possible that the other vector get destroyed in which case any reference from reader threads can become invalide.
So every time your reader thread would access the vector, they would need a lock. So using swap won't help here. The only way it could works is that by ensuring that no reader are active by using some kind of multiple reader - single writer lock.
What might works for you is
std::vector<std::shared_ptr<bigdata_t>> shared_vec;
That way, you only need to properly synchronize the exchange of pointers and ensure that either:
Upvotes: 1