Здравствуйте, netch80, Вы писали:
N>Мне не нравится в нём именно "ручное" освобождение и последующее занятие лока вокруг длительной работы. RAII или with-оператор придумали не просто так, если есть возможность взвалить контроль на них, то лучше этим воспользоваться.
Вопрос к возможностям RAII-примитивов. Например, в C++ std::unique_lock есть дополнительный флажок owns_lock который учитывается при финализации RAII, вот на нем можно сыграть — перенести ручной захват на начало итерации и поставить под условие owns_lock, тогда RAII-автоматика по правильному освоождению лока покроет тот кейс что у тебя покрыт вручную.. Что то типа такого:
std::mutex mtx;
std::condition_variable cv;
bool hasTask = false;
std::thread{
[&]{
std::unique_lock lock{mtx};
for(;;)
{
if(!lock.owns_lock())
lock.lock();
if(!hasTask)
{
cv.wait(lock); // серия холостых ожиданий не приведет к дополнительным перезахватам
continue;
}
hasTask = false;
lock.unlock();
{
//делаем тяжелую задачу
std::this_thread::sleep_for(std::chrono::milliseconds{200});
if(rand() > RAND_MAX/2)
return;// при размотке RAII повторного unlock не случится потому что owns_lock не взведен
if(rand() > RAND_MAX/2)
break;// и так нормально тоже
if(rand() > RAND_MAX/2)
continue;// и так
}
}
}}.join();