Reputation: 97
I was wondering how variable sharing works when I pass things by value. Would I lock a mutex before calling the function, and then unlock inside the function after entering? Is passing by value preferable when working with threads?
Mutex Que_mutex;
queue <char> Que; //access to this must be done with Que_mutex locked
void queSizeCheck(queue<char> quet);
int main() {
//open new threads, which also manipulate Que
//some other code here, where Que.push, Que.pop and Que.front happens at some points
Que_mutex.lock();
queSizeCheck(Que);
}
void queSizeCheck(queue<char> quet) {
Que_mutex.unlock();
if (quet.size() < 3) {
//do something
}
}
I am working on the mbed in C++98.
Upvotes: 2
Views: 759
Reputation: 14714
This is one of the reasons why pass-by-value is kind of broken in C++98.
Since you want to hold the lock for the minimum time possible, in C++11 and C++14 I would copy the queue first, then unlock the mutex, then move the copy into the function (assuming queue
is movable).
int main() {
std::unique_lock<Mutex> lock(Que_mutex);
auto copy = Que;
lock.unlock();
queSizeCheck(std::move(copy));
}
Since the question is tagged C++98, we can't use move semantics. In this case I would encapsulate the copying into a separate function and rely on the compiler being smart enough to apply copy elision:
queue<char> queCopy() {
// lock_guard is C++11 but you can easily write your own C++98 implementation
std::lock_guard<Mutex> lock(Que_mutex);
// hope the compiler is smart enough to directly initialize the parameter
// of queSizeCheck without incurring additional copies
return Que;
}
int main() {
queSizeCheck(queCopy());
}
This relies on the compiler eliding the copy of the return value of queCopy
and of the argument of queSizeCheck
. And ends up with the code actually being more well organised than the C++11 code. Starting in C++17, this once again becomes the better solution, due to mandatory copy elision.
All of this assumes a reasonable implementation of queue
, which wasn't shown in the question.
Upvotes: 4
Reputation: 2355
For sure. You are not even passing the mutex
here. You are using the same mutex
.
It will be unlocked.
Even if you pass the mutex
in the function. It will still be unlocked.
However. It is not smart to lock the mutex
in one function and unlock it in the other.
You should use approach like this.
mutex.lock()
//... some operations on the data structure
mutex.unlock()
You can look at RAII way of doing this with lock_guard.
Upvotes: 0