module Parallel where import Control.Concurrent import Control.Monad (replicateM_) import Data.IORef -- | Does not return results in-order. parallelForM :: [a] -> (a -> IO b) -> IO [b] parallelForM inputList action = do nthread <- getNumCapabilities listref <- newIORef inputList outref <- newIORef [] donechan <- newChan replicateM_ nthread $ forkIO $ let loop = do mitem <- atomicModifyIORef' listref (\case l@[] -> (l, Nothing) item : l -> (l, Just item)) case mitem of Just item -> do res <- action item atomicModifyIORef' outref (\l -> (res : l, ())) loop Nothing -> do writeChan donechan () in loop replicateM_ nthread $ readChan donechan reverse <$> readIORef outref