Как заблокировать переменное количество мьютексов в динамическом контейнере?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Как заблокировать переменное количество мьютексов в динамическом контейнере?

Сообщение Anonymous »

Похожие вопросы:
Вызов std::lock() с помощью std::vector

Блокировка массив std::mutex с использованием массива std::lock_guard
Сводка:
Второй показывает блокировку массивов статического размера, а первый - относится к библиотеке boost::lock(), которая принимает два итератора. Однако boost::lock не поддерживает RAII, как и std::lock. Я ищу решение, как показано ниже

Код: Выделить всё

std::lock(m1, m2);
std::lock_guard l1{m1, std::adopt_lock};
std::lock_guard l2{m2, std::adopt_lock};
или если необходима передача права собственности

Код: Выделить всё

std::unique_lock l1{m1, std::defer_lock};
std::unique_lock l2{m2, std::defer_lock};
std::lock(l1, l2);
или с помощью std::scoped_lock

Код: Выделить всё

std::scoped_lock lk{ m1, m2 };
Однако мьютексы, которые необходимо заблокировать, принадлежат ряду объектов, известных во время выполнения. Следовательно, я не могу использовать std::lock или std::scoped_lock.

Код: Выделить всё

std::vector mutexes{};
mutexes.push_back(std::move(m1));
mutexes.push_back(std::move(m2));
std::scoped_lock lk{ mutexes }; // ERROR
Проект:
У меня есть проект со структурой DAG в центре. DAG содержит отношения «многие к одному» и «один ко многим» и (как и должно быть) поддерживает обходы как в направлении предка, так и в направлении потомка. Чтобы предотвратить тупики, я стараюсь максимально реализовать все алгоритмы только в одном направлении (потомке). Однако в некоторых моментах код неизбежно содержит направление предка. На самом деле, как я объясню на примере ниже, блокировка всегда в одном и том же направлении не решает проблему тупиковой ситуации на 100 процентов. Единственное решение — заблокировать узел DAG вместе со связанными узлами (например, узлами-потомками DAG, если обход осуществляется в направлении потомка). Например, в направлении потомков:

Код: Выделить всё

DAGNode DN{};
std::vector descendants{ DN.get_descendants() };

// Assume we have two descendants
auto& des1{ descendants[0] };
auto& des2{ descendants[1] };
std::scoped_lock lk{DN.m, des1.m, des2.m};
Код для направления предка аналогичен.
Поскольку группа обеспечения доступности баз данных поддерживает отношения «многие к одному» и «один ко многим», DAG настоятельно требует, чтобы блокировка выполнялась вместе, как указано выше. На мой взгляд, такое решение, как определение общего порядка, не выглядит разумным из-за отношений «многие к одному» и «один ко многим». Например, рассмотрим узлы A1, A2, B1, B2, B3, где A1 — предок B1 и B2; A2 является предком B2 и B3. Таким образом, когда A1 участвует в алгоритме (A1, B1, B2) должен быть заблокирован, а (A2, B2, B3) должен быть заблокирован соответственно для A2. Следовательно, B2 должен быть заблокирован в обоих двух обходах, начиная с A1 и A2 соответственно. Это результат отношения «многие к одному», но отношение «один ко многим» также приводит к аналогичным ситуациям. Как видно из этого простого примера, обход в том же направлении также может вызвать тупик (из-за B2). Следовательно, единственным решением является блокировка всех мьютексов одновременно.
Изменить:
Этот проект предназначен для геометрического приложения. Я могу зафиксировать количество узлов-предков, как показано ниже, чтобы получить информацию о размере предков во время компиляции. Например, линейный объект формируется двумя точками. Следовательно, узел DAG, соответствующий строке, будет составлять объект DAGNode.

Код: Выделить всё

template
class DAGNode{
std::mutex _m;
std::array _ancestors;
...
};

class Line{
DAGNode _DN;
...
};
Однако потомки не фиксированы ни для одного объекта. Например, линия может использоваться многими поверхностями или другими объектами.
Подводя итог, мои вопросы:
  • C++ не поддерживает блокировку динамического количества мьютексов (?)
  • Boost поддерживает, но не в стиле RAII (?)
  • Как я могу управлять многими Отношения DAG "-к-одному" и "один-ко-многим" в многопоточном коде при предотвращении взаимоблокировок, если первые два верны?
  • (хотя мне это не кажется разумным) Есть ли какие-либо другие методы/подходы, такие как применение общего заказа?
Изменить: Следующие вопросы не по теме, как прокомментировал @JaMIT
5. я возродил такие известные книги, как Конкуренция в действии, Эффективный современный C++ и т. д. Можете ли вы предложить мне другие источники?
6. Есть ли какая-нибудь библиотека с открытым исходным кодом, которую я могу использовать в этой ситуации?
Большое спасибо.

Подробнее здесь: https://stackoverflow.com/questions/783 ... -container
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»