Я использую библиотеку async
в сочетании с stm
в моей программе.
Основной поток разветвляет два потока, которые работают до тех пор, пока один из них (это может быть один из них) не найдет решение. Решение возвращается через TMVar. Никто из них никогда не ждет на любом TMVar
, кроме как позвонить putTMVar
, когда решение найдено, и один из них гарантированно будет работать вечно, если не будет убит. Итак, как я мог получить «поток, заблокированный на неопределенный срок в транзакции STM» (который, кажется, происходит примерно один раз в двадцать раз), учитывая, что по крайней мере один из дочерних потоков не выполняет блокирующие транзакции STM (или не умирает) до сохранение результата.
Обратите внимание, что два дочерних потока взаимодействуют друг с другом друг с другом , используя TVar
с, но не с TMVar
с.
Упрощенный код:
main :: IO ()
main = do
output <- newEmptyTMVar
result <- withAsync (child1 output) $ \_ -> withAsync (child2 output) $ \_ ->
let go = do
result <- atomically $ takeTMVar output
if someCondition result
then return result
else go
in go
print result
child1 :: TMVar Result -> IO ()
child1 output = go 0
where
go i = do
case computation1 i of
Nothing -> return ()
Just x -> atomically $ putTMVar x
go (i + 1)
child2 :: TMVar Result -> IO ()
-- Does some other stuff, but also only interacts with its argument to
-- give back a result, same as child1.