summaryrefslogtreecommitdiff
path: root/src/Parallel.hs
blob: cc6eb22d352b35b00323382be5fbf7e28145d0f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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