Anselmo GPP
Anselmo GPP

Reputation: 451

Creating multiple lock_guards in a function

I have a class containing a vector full of pointers to std::mutex objects (the number is variable, depending on the user actions) and a member function. In this function, I want to perform some operations, but I need to call all the mutex objects (using std::lock_guard) before I perform these operations to avoid threads conflicts. My first idea was to do it using a for-loop:

for(int i = 0; i < number_of_mutex; i++)
    std::lock_guard<std::mutex> mut[i];

Of course, this didn't work because the lock_guards go out of scope after each iteration. So, I decided to create an outer vector where to store the lock_guards:

std::vector<std::lock_guard<std::mutex>> mut_set;
for(int i = 0; i < number_of_mutex; i++)
    mut_set.push_back(std::lock_guard<std::mutex>(mut[i]));

My program now compiles, but I suspect this may not be correct. The console says "error: use of deleted function":

/home/main.cpp:2162:74:   required from here
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::lock_guard<_Mutex>::lock_guard(const std::lock_guard<_Mutex>&) [with _Mutex = std::mutex]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

Note that lock_guards are non-copyable. How should this situation be solved correctly?

Upvotes: 1

Views: 821

Answers (1)

n314159
n314159

Reputation: 5075

The class std::lock_guard is for good reasons neither copy- nor moveable, since you normally want to use it to lock a scope. Hence it would be bad if you can somehow make it leave its scope (which would happen by passing it to a vector). There is no was around this, since std::vector needs its element type to be moveable or copyable (so it can reallocate/resize, etc.)

You can instead use std::unique_lock. But be careful that nothing bad happens when the thread already owns the mutex (see the page on its constructors).

Another possibility, as Sam already said, is to add another level of indirection and manage the lock_guards with some smart pointer (unique_ptr should also work and I prefer it) that is stored in the vector.

But I agree with what Sam said: rethink your design.

Upvotes: 2

Related Questions