На самом деле плохая идея пытаться контролировать потоки извне. Вы никогда не знаете, в каком состоянии они могут находиться, когда вы их приостанавливаете. Если у них есть блокировка мьютекса на ресурсе, который нужен где-то еще, вы можете легко оказаться в тупиковой ситуации.
Нам пришлось создать «безопасную» функцию приостановки, не прибегая к каким-либо непереносимым расширениям pthread, и я постараюсь вспомнить, как мы это сделали.
Он состоял из мьютекса приостановки для каждого потока и переменной, указывающей состояние потоков. Таким образом, поток, который мы хотим приостановить, будет иметь цикл (в большинстве своем), который будет выглядеть примерно так:
while true:
set mystate = suspended
claim mymutex
yield
release mymutex
set mystate = running
do some work
и код для приостановки / возобновления потока будет:
function suspend (state,mutex):
claim mutex
while state <> suspended:
yield
function resume (state,mutex):
release mutex
while state <> running:
yield
То, что делает приостановка, это в основном блокировка мьютекса и ожидание перехода потока в приостановленное состояние (запись в mystate была сделана только приостановленным и не должна была защищаться другим мьютексом). Функция suspend
не возвращалась, пока не было гарантировано, что задержанный будет остановлен.
Аналогичным образом, возобновление потока освободило мьютекс, чтобы приостановленный мог перезапустить, а затем дождался, пока он перезапустится, прежде чем вернуться.
Это позволило приостановить действие, но под контролем приостановленной нити. Это было намного безопаснее, поскольку он мог гарантировать, что его можно будет приостановить только в безопасных точках, когда у него нет блокировок, которые могли бы заблокировать приложение.