Huy Nhat Tran
Huy Nhat Tran

Reputation: 145

Does std::lock_guard release the mutex after constructed with std::adopt_lock option?

I know my question is quite similar to this Why does std::lock_guard release the lock after using std::adopt_lock?, but the behavior I see is not. Here is my code:

#include <mutex>
#include <iostream>
using namespace std;

std::mutex m;
void fun2();
void fun1() {
    cout << "fun1" << endl;
    std::unique_lock<std::mutex> guard(m);
    cout << "lock mutex" << endl;
    fun2();
    if (guard.owns_lock()) {
        cout << "still holds mutex" << endl;
    }
    else {
        cout << "doesn't hold mutex" << endl;
    }
}
void fun2() {
    std::lock_guard<std::mutex> guard(m, std::adopt_lock);
    cout << "fun2" << endl;
}
int main(int argc, char* argv[]) {
    fun1();
    return 0;
}

And this is the result I get:

fun1
lock mutex
fun2
still holds mutex

Clearly, the unique_lock in fun1 still holds the mutex. So my question is "Does std::lock_guard release the mutex after constructed with std::adopt_lock option?". Hope you all can help me clarify this situation. Thank you.

Upvotes: 4

Views: 1004

Answers (2)

Ted Lyngmo
Ted Lyngmo

Reputation: 118077

The program has undefined behavior.

You've created two guards that both think they own the mutex and they will both unlock it. That's UB.

Using m.lock() in fun1 instead of using a guard would be one way to make it have defined behavior.

Upvotes: 1

Lingxi
Lingxi

Reputation: 14987

When you constructed a std::unique_lock to manage the mutex, you should stick to it unless you first break the association of the std::unique_lock with the mutex using std::unique_lock::release. In your sample, you touched the raw mutex when it's still managed by a std::unique_lock and this is wrong.

Upvotes: 2

Related Questions