module Test.Parallel(main) where import Development.Shake import Test.Type import Data.Foldable import Data.Tuple.Extra import Control.Monad import Control.Concurrent.Extra import Data.IORef main = testBuild test $ do "AB.txt" %> \out -> do -- need [obj "A.txt", obj "B.txt"] (text1,text2) <- readFile' "A.txt" `par` readFile' "B.txt" writeFile' out $ text1 ++ text2 sem <- liftIO $ newQSemN 0 "papplicative_*" %> \out -> do -- wait for both to do the initial start before continuing liftIO $ assertWithin 1 $ do signalQSemN sem 1 waitQSemN sem 3 signalQSemN sem 3 writeFile' out "" phony "papplicative" $ do need ["papplicative_1"] need ["papplicative_2"] let ensureReturn = pure () ensureReturn -- should work even though we have a pure need ["papplicative_3"] "pseparate_*" %> \out -> do liftIO $ appendFile "pseparate.log" "[" liftIO $ sleep 0.1 liftIO $ appendFile "pseparate.log" "]" writeFile' out "" phony "pseparate" $ do need ["pseparate_1"] liftIO $ pure () need ["pseparate_2"] sem <- liftIO $ newQSemN 0 "ptraverse_*" %> \out -> do -- wait for all to do the initial start before continuing liftIO $ assertWithin 1 $ do signalQSemN sem 1 waitQSemN sem 8 signalQSemN sem 8 writeFile' out "" phony "ptraverse" $ traverse_ (need . pure) ["ptraverse_" ++ show i | i <- [1..8]] phony "cancel" $ do writeFile' "cancel" "" done <- liftIO $ newIORef 0 lock <- liftIO newLock void $ parallel $ replicate 5 $ liftIO $ do x <- atomicModifyIORef done $ dupe . succ when (x == 3) $ do sleep 0.1; fail "boom" withLock lock $ appendFile "cancel" "x" phony "parallel" $ do active <- liftIO $ newIORef 0 peak <- liftIO $ newIORef 0 void $ parallel $ replicate 8 $ liftIO $ do now <- atomicModifyIORef active $ dupe . succ atomicModifyIORef peak $ dupe . max now sleep 0.1 atomicModifyIORef active $ dupe . pred peak <- liftIO $ readIORef peak writeFile' "parallel" $ show peak "parallels" %> \out -> do xs <- parallel $ replicate 5 $ parallel $ map pure [1..5] writeFile' out $ show xs phony "timings" $ void $ parallel $ map (liftIO . sleep) [1, 2, 0, 1] test build = do build ["clean"] writeFile "A.txt" "AAA" writeFile "B.txt" "BBB" build ["AB.txt","--sleep"] assertContents "AB.txt" "AAABBB" appendFile "A.txt" "aaa" build ["AB.txt"] assertContents "AB.txt" "AAAaaaBBB" assertException ["boom"] $ build ["cancel","-j1","--quiet"] assertContents "cancel" "xx" build ["parallel","-j1"] assertContents "parallel" "1" build ["parallel","-j5"] assertContents "parallel" "5" build ["parallels"] assertContents "parallels" $ show $ replicate 5 [1..5] writeFile "pseparate.log" "" build ["pseparate","-j2"] assertContents "pseparate.log" "[][]" build ["papplicative","-j3"] build ["ptraverse","-j8"] build ["timings","-j6"] assertTimings build [("timings",4)] build ["timings","-j1"] assertTimings build [("timings",4)]