{-# OPTIONS_GHC -Wno-incomplete-patterns #-} module Main (main) where import Control.Concurrent import Control.Exception qualified as Ex import Control.Monad import Data.Acquire qualified as A import Data.Function import Data.IORef import Data.List qualified as List import Data.Time qualified as Time import Job import Job.Memory qualified import System.Random.Stateful qualified as R -------------------------------------------------------------------------------- infix 4 ==. (==.) :: (Eq a, Show a) => a -> a -> IO () (==.) l r = if l == r then mempty else fail $ (showsPrec 11 l . showString " /= " . showsPrec 11 r) "" infix 4 >. (>.) :: (Ord a, Show a) => a -> a -> IO () (>.) l r = if l > r then mempty else fail $ (showsPrec 11 l . showString " <= " . showsPrec 11 r) "" main :: IO () main = A.withAcquire (Job.Memory.queue @String) \q -> do t0 <- Time.getCurrentTime putStrLn "a" [] <- prune q \i m j -> (False, [(i, m, j)]) putStrLn "b" i0 <- push q nice0 t0 "j0" [(x0i, x0m, x0j)] <- prune q \i m j -> (False, [(i, m, j)]) x0i ==. i0 x0j ==. "j0" x0m.nice ==. nice0 x0m.wait ==. t0 x0m.try ==. 0 x0m.alive ==. Nothing [] <- prune q \i m j -> (False, [(i, m, j)]) putStrLn "c" i1 <- push q nice0 t0 "j1" [(x1i, x1m, x1j)] <- prune q \i m j -> (True, [(i, m, j)]) x1i ==. i1 x1j ==. "j1" x1m.nice ==. nice0 x1m.wait ==. t0 x1m.try ==. 0 x1m.alive ==. Nothing putStrLn "d" [(x2i, x2m, x2j)] <- prune q \i m j -> (True, [(i, m, j)]) x2i ==. i1 x2j ==. "j1" x2m.nice ==. nice0 x2m.wait ==. t0 x2m.try ==. 0 x2m.alive ==. Nothing putStrLn "e" t1 <- Time.getCurrentTime A.withAcquire q.pull $ mapM_ \w -> do putStrLn "e'" w.id ==. i1 w.job ==. "j1" w.meta.nice ==. nice0 w.meta.wait ==. t0 w.meta.try ==. 0 retry w (Nice 1) t1 putStrLn "f" [(x3i, x3m, x3j)] <- prune q \i m j -> (True, [(i, m, j)]) x3i ==. i1 x3j ==. "j1" x3m.nice ==. Nice 1 x3m.wait ==. t1 x3m.try ==. 1 x3m.alive ==. Nothing putStrLn "g" A.withAcquire q.pull $ mapM_ \w -> do putStrLn "g'" w.id ==. i1 w.job ==. "j1" w.meta.nice ==. Nice 1 w.meta.wait ==. t1 w.meta.try ==. 1 retry w (Nice 1) t1 putStrLn "h" [(x4i, x4m, x4j)] <- prune q \i m j -> (True, [(i, m, j)]) x4i ==. i1 x4j ==. "j1" x4m.nice ==. Nice 1 x4m.wait ==. t1 x4m.try ==. 2 x4m.alive ==. Nothing putStrLn "i" A.withAcquire q.pull $ mapM_ \w -> do putStrLn "i'" w.id ==. i1 w.job ==. "j1" w.meta.nice ==. Nice 1 w.meta.wait ==. t1 w.meta.try ==. 2 pure () putStrLn "j" [] <- prune q \i m j -> (True, [(i, m, j)]) t2 <- Time.addUTCTime 0.3 <$> Time.getCurrentTime i2 <- push q nice0 t2 "j2" [(x5i, x5m, x5j)] <- prune q \i m j -> (True, [(i, m, j)]) x5i ==. i2 x5j ==. "j2" x5m.nice ==. nice0 x5m.wait ==. t2 x5m.try ==. 0 x5m.alive ==. Nothing putStrLn "k" Ex.handle (\case Err 1 -> pure ()) do A.withAcquire q.pull $ mapM_ \w -> do putStrLn "k'" w.id ==. i2 w.job ==. "j2" w.meta.nice ==. nice0 w.meta.wait ==. t2 w.meta.try ==. 0 void $ Ex.throwIO $ Err 1 putStrLn "l" [(x6i, x6m, x6j)] <- prune q \i m j -> (True, [(i, m, j)]) x6i ==. i2 x6j ==. "j2" x6m.nice ==. nice0 x6m.wait >. t2 x6m.try ==. 1 x6m.alive ==. Nothing putStrLn "m" i3 <- push q nice0 t0 "j3" i4 <- push q (pred nice0) t1 "j4" i5 <- push q nice0 t0 "j5" jIds0 <- prune q \i _ _ -> (True, [i]) jIds0 ==. [i4, i3, i5, i2] putStrLn "n" forM_ (zip jIds0 (List.drop 1 (List.tails jIds0))) \(jId, tl) -> A.withAcquire q.pull $ mapM_ \w -> do w.id ==. jId jIds1 <- prune q \i _ _ -> (True, [i]) jIds1 ==. tl <> [jId] [] <- prune q \i m j -> (True, [(i, m, j)]) putStrLn "o" do t3 <- Time.getCurrentTime rwout <- newIORef ([] :: [String]) let wins :: [String] = fmap show [0 .. 1000 :: Word] forM_ wins \win -> do wrd :: Word <- R.uniformM R.globalStdGen let pct = toRational wrd / toRational (maxBound :: Word) ndt = fromRational (pct * 0.5) push q nice0 (Time.addUTCTime ndt t3) win putStrLn "o'" replicateM_ 4 $ forkIO $ fix \again -> do y <- A.withAcquire q.pull $ mapM \w -> atomicModifyIORef' rwout \xs -> (w.job : xs, ()) forM_ y \_ -> again threadDelay 3_100_000 [] <- prune q \i m j -> (True, [(i, m, j)]) wout <- readIORef rwout length wout ==. length wins List.sort wout ==. List.sort wins putStrLn "done" data Err = Err Int deriving stock (Eq, Show) deriving anyclass (Ex.Exception)