std::mutex best practice
Asked Answered
P

2

5

Since when an exception is thrown the only code is ensured to being run is the destructor, code like this might generate a memory leak

std::mutex foo;
foo.lock();
// My code which might throw an exception
foo.unlock();

Is it a best practice do something similar to this or might there is other better option? The idea is taking advantage of RAII in order to ensure than mutex will be freed if exception is thrown.

std::mutex foo;
{
    std::lock_guard<std::mutex>(foo);
    // My code which might throw an exception
}
Polyandry answered 18/6, 2019 at 8:57 Comment(2)
Well, usually it is best practice. If you want to unlock it before scope ends, you could use std::unique_lock instead, but there's nothing to be gained by managing mutex manully (except for headache and bugs).Mingmingche
std::lock_guard<std::mutex>(foo); does not guard anything since unnamed temporary variable is immediately destroyed so // My code will be executed when mutex is not locked.Petepetechia
M
13

Is it a best practice do something similar to this?

std::mutex foo;
{
    std::lock_guard<std::mutex>(foo);
    // My code which might throw an exception
}

No! You are creating an unnamed temporary variable here with a lifetime that ends at the end of the line. Instead, make sure that the object has a name, such that its lifetime meets that of its scope.

std::mutex foo;
{
    std::lock_guard<std::mutex> NEVER_FORGET_THIS_NAME(foo);
    // My code which might throw an exception
}

But besides, generally - yes, it is good practice to use RAII in this situation. And also note that the unnamed-lockguard bug is not uncommon, have a look here.

Mojave answered 18/6, 2019 at 8:59 Comment(1)
I don't want to be nitpicker, but temporary object can be constructed only if {} were used - std::lock_guard<std::mutex>{foo}; in this case we have temporary lock_guard, but in this std::lock_guard<std::mutex>(foo); code cannot compile becaues there is no lock_guard constructor taking no arguments - mutex is required. The code std::unique_lock<std::mutex>(foo) creates foo instance which ctor takes no mutex, so there is no lock in construction and there is no unlock at destruction, but foo as unique_lock exists until the end of scope. demoBodycheck
A
0

Always use lock_guard to ensure that mutex will be released.

Allodial answered 18/6, 2019 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.