«поток заблокирован на неопределенный срок в транзакции STM» в случае, когда потоки никогда не блокируются - PullRequest
0 голосов
/ 29 августа 2018

Я использую библиотеку 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.
...