Ho creato questo piccolo programma che crea un thunk long-running che alla fine fallisce con un'eccezione. Quindi, più thread cercano di valutarlo.Se un thunk risulta in un'eccezione, l'eccezione viene mantenuta come risultato del thunk?
import Control.Monad
import Control.Concurrent
import Control.Concurrent.MVar
main = do
let thunk = let p = product [1..10^4]
in if p `mod` 2 == 0 then error "exception"
else()
children <- replicateM 2000 (myForkIO (print thunk))
mapM_ takeMVar children
-- | Spawn a thread and return a MVar which can be used to wait for it.
myForkIO :: IO() -> IO (MVar())
myForkIO io = do
mvar <- newEmptyMVar
forkFinally io (\_ -> putMVar mvar())
return mvar
Aumentando il numero di fili ha chiaramente alcun impatto sul calcolo, il che suggerisce che un thunk fallito mantiene l'eccezione come risultato. È vero? Questo comportamento è documentato/specificato da qualche parte?
Aggiornamento: Modificando la riga forkFinally
di
forkFinally io (\e -> print e >> putMVar mvar())
conferma che ogni filo riesce con l'eccezione.
L'eccezione * è * il valore dell'espressione. Cos'altro potrebbe fare la valutazione dell'espressione più volte? – Carl
@Carl Questo è quello che sospetto, ma voglio essere sicuro. Potrebbe anche provare a ricalcolare il valore ancora e ancora. –
Conosco gli interni di GHC, altrimenti non potrei creare strumenti come 'ghc-heap-view', quindi non sono sicuro di cos'altro ti serve. Puoi chiarire la tua domanda se la mia risposta non è abbastanza utile? –