Сообщение Re: Multithreading: как очередь, но вручную и красиво? от 15.01.2026 19:30
Изменено 15.01.2026 19:31 antropolog
Re: Multithreading: как очередь, но вручную и красиво?
Здравствуйте, netch80, Вы писали:
N>Периодически возникает при многонитевом построении примерно следующий "паттерн": есть элемент состояния/управления (как очередь заданий), который требует контролируемого взаимодействия с помощью лока и "условной переменной". Но чтобы на время выполнения задания не блокировать тех, кто хочет установить следующее задание, лок снимается на это время. Получается следующая схема:
N>
N>Мне не нравится в нём именно "ручное" освобождение и последующее занятие лока вокруг длительной работы. RAII или with-оператор придумали не просто так, если есть возможность взвалить контроль на них, то лучше этим воспользоваться.
N>Можно было бы просто перевести на очередь. Но бывает, что при этом ещё и какие-то элементы статуса отдаются обратно, или воздействие от управляющего метода более сложное. И если может быть поставлено не более одного задания, то делать это в виде очереди, ограниченной одним элементом, тоже как-то странно. Ещё бывают собственные idle операции, а ждать чтения из очереди с таймаутом не всегда возможно.
N>Какие есть варианты сделать это красиво без подобных ручных плясок?
кмк если такое действительно уже стало паттерном, то оптимальней будет один раз написать хелпер а-ля InvertedLock c _enter_/_exit_ протоколом, для поддержки with и будет то же самое только raii-like
N>Периодически возникает при многонитевом построении примерно следующий "паттерн": есть элемент состояния/управления (как очередь заданий), который требует контролируемого взаимодействия с помощью лока и "условной переменной". Но чтобы на время выполнения задания не блокировать тех, кто хочет установить следующее задание, лок снимается на это время. Получается следующая схема:
N>
N>## Псевдокод в стиле Python
N>with self.lock: ## для C++ аналог -- захват лока в конструкторе
N> while True:
N> if not self.task: ## можно было и с предикатом, если кому удобнее читать
N> self.cv.sleep()
N> continue
N> task = self.task
N> self.task = None
N> self.lock.release() ## начинается длительная операция
N> try:
N> self.execute(task)
N> except Exception:
N> ... пожаловались ...
N> self.lock.acquire()
N>N>Мне не нравится в нём именно "ручное" освобождение и последующее занятие лока вокруг длительной работы. RAII или with-оператор придумали не просто так, если есть возможность взвалить контроль на них, то лучше этим воспользоваться.
N>Можно было бы просто перевести на очередь. Но бывает, что при этом ещё и какие-то элементы статуса отдаются обратно, или воздействие от управляющего метода более сложное. И если может быть поставлено не более одного задания, то делать это в виде очереди, ограниченной одним элементом, тоже как-то странно. Ещё бывают собственные idle операции, а ждать чтения из очереди с таймаутом не всегда возможно.
N>Какие есть варианты сделать это красиво без подобных ручных плясок?
кмк если такое действительно уже стало паттерном, то оптимальней будет один раз написать хелпер а-ля InvertedLock c _enter_/_exit_ протоколом, для поддержки with и будет то же самое только raii-like
Re: Multithreading: как очередь, но вручную и красиво?
Здравствуйте, netch80, Вы писали:
N>Мне не нравится в нём именно "ручное" освобождение и последующее занятие лока вокруг длительной работы. RAII или with-оператор придумали не просто так, если есть возможность взвалить контроль на них, то лучше этим воспользоваться.
N>Можно было бы просто перевести на очередь. Но бывает, что при этом ещё и какие-то элементы статуса отдаются обратно, или воздействие от управляющего метода более сложное. И если может быть поставлено не более одного задания, то делать это в виде очереди, ограниченной одним элементом, тоже как-то странно. Ещё бывают собственные idle операции, а ждать чтения из очереди с таймаутом не всегда возможно.
N>Какие есть варианты сделать это красиво без подобных ручных плясок?
кмк если такое действительно уже стало паттерном, то оптимальней будет один раз написать хелпер а-ля InvertedLock c _enter_/_exit_ протоколом, для поддержки with и будет то же самое только raii-like
N>Мне не нравится в нём именно "ручное" освобождение и последующее занятие лока вокруг длительной работы. RAII или with-оператор придумали не просто так, если есть возможность взвалить контроль на них, то лучше этим воспользоваться.
N>Можно было бы просто перевести на очередь. Но бывает, что при этом ещё и какие-то элементы статуса отдаются обратно, или воздействие от управляющего метода более сложное. И если может быть поставлено не более одного задания, то делать это в виде очереди, ограниченной одним элементом, тоже как-то странно. Ещё бывают собственные idle операции, а ждать чтения из очереди с таймаутом не всегда возможно.
N>Какие есть варианты сделать это красиво без подобных ручных плясок?
кмк если такое действительно уже стало паттерном, то оптимальней будет один раз написать хелпер а-ля InvertedLock c _enter_/_exit_ протоколом, для поддержки with и будет то же самое только raii-like
with self.lock: ## для C++ аналог -- захват лока в конструкторе
while True:
if not self.task: ## можно было и с предикатом, если кому удобнее читать
self.cv.sleep()
continue
task = self.task
self.task = None
self.lock.release() ## начинается длительная операция
with invertedLock = InvertedLock(self.lock):
try:
self.execute(task)
except Exception:
... пожаловались ...