M>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить.
Просто пропустить, вывешивать в ожидание не надо?
M>Пока придумалась такая схема (псевдокод): M>Ну или как лучше сделать? Может, есть что-то стандартное, чем изобретать велосипеды?
Если тормозить поток на нем не надо, то такая схема ок. Разве что два атомика тут лишние. Один класс lockable со счетчиком, лочить через std::lock_guard.
Здравствуйте, andrey.desman, Вы писали:
M>>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить.
AD>Просто пропустить, вывешивать в ожидание не надо?
Да, именно так
M>>Пока придумалась такая схема (псевдокод): M>>Ну или как лучше сделать? Может, есть что-то стандартное, чем изобретать велосипеды?
AD>Если тормозить поток на нем не надо, то такая схема ок. Разве что два атомика тут лишние. Один класс lockable со счетчиком, лочить через std::lock_guard.
Лишний атомик в булевском флаге, я правильно понял?
Здравствуйте, Marty, Вы писали:
M>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить.
Хотя не понятно, что значит запрещать? Если поток уже что-то делает запрещенное, а ты запретил, это будет ок? Или нужна критсекция все-таки?
Наверное тебе подойдет std::shared_mutex.
Здравствуйте, andrey.desman, Вы писали:
AD>Здравствуйте, Marty, Вы писали:
M>>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить.
AD>Хотя не понятно, что значит запрещать? Если поток уже что-то делает запрещенное, а ты запретил, это будет ок?
Нормас, главное, чтобы потом в следующий раз пропустил
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, vopl, Вы писали:
M>>>Ну или как лучше сделать? Может, есть что-то стандартное, чем изобретать велосипеды?
V>>У тебя получился Семафор
M>Семафор блокирующий примитив
У тебя он тоже блокирующий, только блокирует не поток а семантику. Это всего лишь вопрос точки зрения. Но, хозяин барин, пусть это не Семафор
Здравствуйте, vopl, Вы писали:
M>>Семафор блокирующий примитив V>У тебя он тоже блокирующий, только блокирует не поток а семантику. Это всего лишь вопрос точки зрения. Но, хозяин барин, пусть это не Семафор
Да пусть и семафор
Окай, семафор, где у нас есть проверяющий неблокирующий семафор?
Чтобы не потерять разблокировку, удобнее использовать raii, а не руками вызывать Lock (если код конечно позволяет)
тогда счетчик можно перенести в класс Locable.
Здравствуйте, tryAnother, Вы писали:
A>Чтобы не потерять разблокировку, удобнее использовать raii, а не руками вызывать Lock (если код конечно позволяет)
Это высшая магия, естественно, я её буду использовать. Когда будет надо. Например, в скопах
M>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить.
M>В других потоках, или в том же потоке, можно запрещать, рекурсивно, главное, разлочить столько же раз, сколько и залочил.
M>Что-то городить с какими-то примитивами синхронизации не вижу смысла, ну, может я ошибаюсь.
...
M>Ну или как лучше сделать? Может, есть что-то стандартное, чем изобретать велосипеды?
Здравствуйте, vopl, Вы писали:
V>У тебя получился Семафор
Не получился, потому что у семафора семантика "поднял где угодно кто угодно" / "опустил и ждёшь".
А тут — один поднял-опустил без блокировки, другой пытается пролезть и ждёт.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, vopl, Вы писали:
V>>У тебя получился Семафор
К>Не получился, потому что у семафора семантика "поднял где угодно кто угодно" / "опустил и ждёшь". К>А тут — один поднял-опустил без блокировки, другой пытается пролезть и ждёт.
Ну, это если смотреть со стороны его реализации в конкретных схемах вытесняющего многопотока. Чуть абстрактнее если подняться, то семафор это "... счётчик, над которым можно производить две атомарные операции: увеличение и уменьшение значения на единицу, при этом операция уменьшения для нулевого значения счётчика является блокирующейся...". Вот по такой семантике у него вполне семафор, ноль как граница блокируемости, выше ноля свободно, ноль и ниже — заблокировано (или наоборот, не важно). Хотя, это все вопрос трактовки, спорить не стану, просто поясняю свой ход мыслей.
Здравствуйте, Marty, Вы писали:
M>Где-то в каком-то потоке периодически что-то производится, какие-то действия. Иногда надо временно запретить их производить. M>В других потоках, или в том же потоке, можно запрещать, рекурсивно, главное, разлочить столько же раз, сколько и залочил.
Если не вдаваться в подробности, то правда ли, что апи получается такой? Назовём эту штуку "дверь". Потому что поток проходит через неё и дальше занимается своими делами.
struct Door {
int level = 0;
bool is_open() const { return level > 0; }
// апи управляющей стороны (не ждёт) (меняет состояние двери)void open() { ++level; }
void close() { --level; }
// апи управляемой стороны (не меняет состояние двери)bool try_pass() const { return is_open(); } // не ждётbool pass(auto timeout) const { WAIT(timeout, is_open); return is_open(); }
void pass() const { WAIT(is_open); }
}
и в этом случае ему нужна внешняя помощь — какой-то другой поток должен отпереть эту дверь
M>Что-то городить с какими-то примитивами синхронизации не вижу смысла, ну, может я ошибаюсь.
Примитивы синхронизации стоят дёшево, пока не попадают на блокировку.
Но если очень хочется упороться по лок-фри и написать своё, заведомо userspace, то ради бога.
Семафоры и мьютексы, будучи симметричными инструментами, тут не подойдут. (Не, конечно, на паре семафоров можно построить абсолютно все производные примитивы).
А вот на кондеях такое делается элементарно
Здравствуйте, vopl, Вы писали:
V>Ну, это если смотреть со стороны его реализации в конкретных схемах вытесняющего многопотока. Чуть абстрактнее если подняться, то семафор это "... счётчик, над которым можно производить две атомарные операции: увеличение и уменьшение значения на единицу, при этом операция уменьшения для нулевого значения счётчика является блокирующейся...". Вот по такой семантике у него вполне семафор, ноль как граница блокируемости, выше ноля свободно, ноль и ниже — заблокировано (или наоборот, не важно). Хотя, это все вопрос трактовки, спорить не стану, просто поясняю свой ход мыслей.
Семафор — счётчик расхода ресурсов. Его нельзя просто так отпереть так, что "работайте все кто хочет сколько хочет".
И его нельзя рекурсивно запереть так, что сам остался на свободе.
Ну и как строительный кирпич — семафор люто неудобная штука.
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, reversecode, Вы писали:
R>>std::recursive_mutex не оно?
M>Он же рекурсивен только для захватившего потока, для остальных блокирует, не?
А данные в том потоке, в который иногда можно динамить, не те ли используются, что в других потоках? Не нужно ли лочить мьютекс в этом потоке так, чтобы другие подождали?
А так std::shared_mutex(C++17) или std::shared_timed_mutex(C++14). Для гурьбы потоков использовать lock_shared/unlock_shared, и try_lock для потока, который динамят
Но это не точно. Я такую разновидность мьютексов ещё не использовал. Что там с рекурсивностью — х.з.