packman-0.3.0: Test/TestMThread.hs
-- testing serialisation with multiple concurrent threads
import GHC.Packing
import qualified Data.Array.IArray as A
import Control.Concurrent
import System.Environment
import System.IO
import System.Directory
import System.Exit
import qualified Data.ByteString as B
import Control.Exception
-- need a time-wasting function which allocates...
nfib :: Integer -> Integer
nfib 0 = 1
nfib 1 = 1
nfib n = let n1 = nfib (n-1)
n2 = nfib (n-2)
in 1 + 2*n1 + n2 - n1
fib :: Int -> Int
fib x | x <= 1 = 1
|otherwise = fib (x-1) + fib (x-2)
-- | duplicate data
duplicate :: a -> IO a
duplicate x = (deserialize =<< trySerialize x)
testeval :: (Show b) => String -> a -> (a -> b) -> String -> IO ()
testeval name dat f expected
= do putStr name
dat' <- duplicate dat
let out = show (f dat')
if (out /= expected)
then do putStrLn (": FAILED\t unexpected " ++ out)
error (name ++ " failed")
else putStrLn (": OK\t" ++ out)
main
= do hSetBuffering stdout NoBuffering
args <- getArgs
let u = if (null args) then 40 else read (head args)
n = if length args < 2 then 10 else read (args!!1)
putStrLn "Multithreaded test program for serialisation"
let input = [20..u]
flt = filter (> 10000)
fibL = (flt . map fib) input
-- [10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269]
putStrLn "normal evaluation (take 3), should be \n[10946,17711,28657]"
putStrLn (show $ take 3 fibL)
let doThread i =
do v <- newEmptyMVar
-- note that all threads use fibL. Many calls to
-- trySerialize will block on blackholes (the core
-- operation will block and retry)
forkIO (do testeval (show i)
(cycle fibL) (!!i)
(show (fibL!!(i `mod` length fibL)))
putMVar v ())
return v
vs <- mapM doThread [0..n-1]
putStrLn "forked, waiting"
mapM_ takeMVar vs
putStrLn "done"
{-
let f2 x y = fib (x+y)
testeval "packing a function (2 arg.s)" f2
(\f -> (take 3 . flt . map (f 0)) input)
"[10946,17711,28657]"
let f3 x a b c y d = head $ map (map fib)
[[(x+a+b+c+d)-const .. (y+a+b+c+d)-const ]]
const = head fibL - 1
f3' = f3 (head fibL) 0 0
const `seq` f3' `seq`
testeval "packing a list function (2 arg.s, 1 supplied)"
f3' (\f -> take 3 (flt (f 0 (u+const) 0)))
"[10946,17711,28657]"
putStrLn "DONE"
let n = max 10 u
size = 3*u -- default 120
arr :: A.Array Int Int
arr = A.array (0,size-1)
[ (i,i) | i <- [0..size-1] ]
output = A.amap (2*) arr
-- output some of the original elements
putStrLn $ show $ take n $ A.elems arr
testeval "packing an unevaluated array"
output (take n . A.elems)
(show (take n [0,2..]))
-}