C++11 std::condition_variable: можем ли мы передать нашу блокировку непосредственно уведомленному потоку?

Я изучаю параллелизм C++11, где мой единственный предыдущий опыт работы с примитивами параллелизма был на курсе операционных систем шесть лет назад, так что будьте осторожны, если вы можете.

В C++11 мы можем написать

std::mutex m;
std::condition_variable cv;
std::queue q;

void producer_thread() {
    std::unique_lock lock(m);
    q.push(42);
    cv.notify_one();
}

void consumer_thread() {
    std::unique_lock lock(m);
    while (q.empty()) {
        cv.wait(lock);
    }
    q.pop();
}

Это прекрасно работает, но меня раздражает необходимость оборачивать cv.waitв цикл. Причина, по которой нам нужен цикл, мне ясна:

Consumer (inside wait())       Producer            Vulture

release the lock
sleep until notified
                               acquire the lock
                               I MADE YOU A COOKIE
                               notify Consumer
                               release the lock
                                                   acquire the lock
                                                   NOM NOM NOM
                                                   release the lock
acquire the lock
return from wait()
HEY WHERE'S MY COOKIE                              I EATED IT

Теперь я считаю, что одна из замечательных особенностей unique_lockзаключается в том, что мы можем передавать его, верно? Так что было бы очень элегантно, если бы мы могли сделать это вместо этого:

Consumer (inside wait())       Producer

release the lock
sleep until notified
                               acquire the lock
                               I MADE YOU A COOKIE
                               notify and yield(passing the lock)
wake(receiving the lock)
return from wait()
YUM
release the lock

Теперь у потока Vulture нет возможности налететь, потому что мьютекс остается заблокированным на всем пути от I MADE YOU A COOKIEдо НЮМ. Кроме того, если notify()требует, чтобы вы передали блокировку, это хороший способ гарантировать, что люди действительно заблокируют мьютекс перед вызовом notify()(см. Сигнализация состояния переменная (pthreads)).

Я почти уверен, что C++11 не имеет стандартной реализации этой идиомы.Какова историческая причина этого (просто pthreads этого не делал? и тогда почему это)? Есть ли техническая причина, по которой предприимчивый программист C++ не смог реализовать эту идиому в стандартном C++11, назвав ее, возможно, my_better_condition_variable?

У меня также есть смутное ощущение, что, может быть, я заново изобретаю семафоры, но я недостаточно помню из школы, чтобы знать, верно это или нет.

14
задан Community 23 May 2017 в 12:13
поделиться