std :: unique_lock переместить семантику - PullRequest
1 голос
/ 15 января 2020

Пожалуйста, помогите мне проверить, правильно ли мое понимание std::unique_lock move semanti c.
Допустим, у меня есть функция myFunc, которая должна получить мьютекс в начале своего выполнения.
Эта функция вызывается из разных функций, некоторые из них, например, myWrapper1 содержат один и тот же мьютекс перед вызовом myFunc.
Иногда мне нужно, чтобы эта блокировка не снималась при выходе из области действия myFunc.

typedef std::unique_lock<std::mutex> MyLock;
class Example2
{
    std::mutex m_data_mutex;

    MyLock&& myFunc(MyLock&& lk)
    {
        bool was_lock = lk.owns_lock();
        if( !was_lock ) lk.lock();

        std::cout << "myFunc" << std::endl;

        if( !was_lock ) lk.unlock();
        return std::move(lk);
    }

    void myWrapper1()
    {
        MyLock lk(m_data_mutex);
        std::cout << "1" << std::endl;
        lk = myFunc(std::move(lk));
        std::cout << "2" << std::endl;
    }

    void myWrapper2()
    {
        MyLock lk(m_data_mutex);
        std::cout << "1" << std::endl;
        lk.unlock();
        lk = myFunc(std::move(lk));
        std::cout << "2" << std::endl;
        lk.lock();
        std::cout << "3" << std::endl;
    }
};

Итак, вопросы:

  1. для myWrapper1 есть гарантия, что MyLock будет выпущен только в конце myWrapper1, не так ли?
  2. Использую ли я правильную идиому для этой проблемы?

1 Ответ

2 голосов
/ 15 января 2020

Есть ли какая-то причина, почему вы не можете сделать что-то подобное вместо этого? ИМО, это намного более чисто, чем перемещение замков от владельца к владельцу.

std::mutex my_lock;

void myFunc_locked() {
    ...do something that requires my_lock to be locked...
}

void myFunc() {
    std::lock_guard<std::mutex> guard(my_lock);
    myFunc_locked();
}

void myWrapper1() {
    std::lock_guard<std::mutex> guard(my_lock);
    ...do something else that requires my_lock to be locked...
    myFunc_locked();
}

void myWrapper2() {
    ...
    myFunc();
}

Или сделайте так, как предложил @Nevin. Может быть, еще чище:

std::mutex my_lock;

void myFunc(std::lock_guard<std::mutex>> const& guard) {
    ...do something that requires my_lock to be locked...
}

void myFunc() {
    std::lock_guard<std::mutex> guard(my_lock);
    myFunc(guard);
}

void myWrapper1() {
    std::lock_guard<std::mutex> guard(my_lock);
    ...do something else that requires my_lock to be locked...
    myFunc(guard);
}

void myWrapper2() {
    ...
    myFunc();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...