Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use something like std::vector<std::mutex>?

I have a large, but potentially varying, number of objects which are concurrently written into. I want to protect that access with mutexes. To that end, I thought I use a std::vector<std::mutex>, but this doesn't work, since std::mutex has no copy or move constructor, while std::vector::resize() requires that.

What is the recommended solution to this conundrum?

edit: Do all C++ random-access containers require copy or move constructors for re-sizing? Would std::deque help?

edit again

First, thanks for all your thoughts. I'm not interested in solutions that avoid mutices and/or move them into the objects (I refrain from giving details/reasons). So given the problem that I want a adjustable number of mutices (where the adjustment is guaranteed to occur when no mutex is locked), then there appear to be several solutions.

1 I could use a fixed number of mutices and use a hash-function to map from objects to mutices (as in Captain Oblivous's answer). This will result in collisions, but the number of collisions should be small if the number of mutices is much larger than the number of threads, but still smaller than the number of objects.

2 I could define a wrapper class (as in ComicSansMS's answer), e.g.

struct mutex_wrapper : std::mutex {   mutex_wrapper() = default;   mutex_wrapper(mutex_wrapper const&) noexcept : std::mutex() {}   bool operator==(mutex_wrapper const&other) noexcept { return this==&other; } }; 

and use a std::vector<mutex_wrapper>.

3 I could use std::unique_ptr<std::mutex> to manage individual mutexes (as in Matthias's answer). The problem with this approach is that each mutex is individually allocated and de-allocated on the heap. Therefore, I prefer

4 std::unique_ptr<std::mutex[]> mutices( new std::mutex[n_mutex] );

when a certain number n_mutex of mutices is allocated initially. Should this number later be found insufficient, I simply

if(need_mutex > n_mutex) {   mutices.reset( new std::mutex[need_mutex] );   n_mutex = need_mutex; } 

So which of these (1,2,4) should I use?

like image 791
Walter Avatar asked May 09 '13 15:05

Walter


People also ask

What is std :: vector used for?

What is std::vector<T> v;? It is a template class that will wrap an array of Ts. In this widely used notation, 'T' stands for any data type, built-in, or user-defined class.

How does STD mutex work?

The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads. mutex offers exclusive, non-recursive ownership semantics: A calling thread owns a mutex from the time that it successfully calls either lock or try_lock until it calls unlock .

Can std :: mutex be copied?

std::mutex::mutexmutex objects cannot be copied/moved (both the copy constructor and assignment operator are deleted for this type).

Is std :: mutex thread safe?

It is totally safe for multiple threads to read the same variable, but std::mutex can not be locked by multiple threads simultaneously, even if those threads only want to read a value. Shared mutexes and locks allow this.


2 Answers

vector requires that the values are movable, in order to maintain a contiguous array of values as it grows. You could create a vector containing mutexes, but you couldn't do anything that might need to resize it.

Other containers don't have that requirement; either deque or [forward_]list should work, as long as you construct the mutexes in place either during construction, or by using emplace() or resize(). Functions such as insert() and push_back() will not work.

Alternatively, you could add an extra level of indirection and store unique_ptr; but your comment in another answer indicates that you believe the extra cost of dynamic allocation to be unacceptable.

like image 126
Mike Seymour Avatar answered Sep 17 '22 09:09

Mike Seymour


If you want to create a certain length:

std::vector<std::mutex> mutexes; ... size_t count = 4; std::vector<std::mutex> list(count);  mutexes.swap(list); 
like image 34
Awwit Avatar answered Sep 21 '22 09:09

Awwit