I would like to store a variable number of mutexes in a container like vector or deque.
In one of the use cases, I need to reliably and deadlock-free lock all of the mutexes. I would also like to have exception safety guarantee, that if an exception is thrown, all of the mutexes are as if no locking occured.
I am trying to do something like:
std::vector<std::mutex> locks_(n);
std::vector<std::lock_guard<std::mutex> > guards(n);
for(int i = 0; i < n; i++) {
std::lock_guard<std::mutex> guard(locks_[i]);
guards.emplace_back(std::move(guard));
}
but it doesn't compile, giving me:
/usr/include/c++/4.8/ext/new_allocator.h:120:4: error: use of deleted function ‘std::lock_guard<_Mutex>::lock_guard(const std::lock_guard<_Mutex>&) [with _Mutex = std::mutex]’
I guess there might also be a problem when lock_guards are destroyed, because the order must be reversed as compared to construction, but the standard saves us with:
The delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted. In the case of an array, the elements will be destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see 12.6.2).
Are there any potential pitfalls with this approach and how can one make it work?
Edit
actually I am wrong, it seems vector does not guarantee a particular order of destruction. See this question: Order of destruction of elements of an std::vector
Edit2
Q: What if the use case is:
All the mutexes are locked/unlocked in any order by different threads (however each of those threads uses only 1 mutex at a time), but at some point I need to lock all of the mutexes in a safe manner in another thread.