{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} import Control.Concurrent import Control.Exception import Control.Monad import Data.Fixed (E6, Fixed(..)) import Data.IORef import Data.TimerWheel import System.Random main :: IO () main = do do putStrLn "Timer wheel runs scheduled actions" let n = 10000 ref <- newIORef (0::Int) wheel <- create Config { spokes = 4, resolution = 0.25 } putStrLn ("> Inserting " ++ show n ++ " timers") replicateM_ n $ do delay <- randomRIO (0, 4*1000*1000) register_ wheel (modifyIORef' ref (+1)) (MkFixed delay) putStrLn "> Sleeping for 5s" sleep 5 readIORef ref `is` n destroy wheel do putStrLn "Timers can be canceled" let n = 10000 ref <- newIORef (0::Int) wheel <- create Config { spokes = 4, resolution = 0.25 } putStrLn ("> Inserting " ++ show n ++ " timers") cancels <- replicateM n $ do delay <- randomRIO (0, 4*1000*1000) register wheel (modifyIORef' ref (+1)) (MkFixed delay) putStrLn "> Sleeping for 2s" sleep 2 putStrLn "> Canceling all timers" successes <- sequence cancels readIORef ref `is` (n - length (filter id successes)) destroy wheel do putStrLn "Re-calling a successful cancel works" wheel <- create Config { spokes = 4, resolution = 0.25 } cancel <- register wheel (pure ()) 1 cancel `is` True cancel `is` True destroy wheel do putStrLn "Re-calling a failed cancel works" wheel <- create Config { spokes = 4, resolution = 0.25 } cancel <- register wheel (pure ()) 0.5 sleep 1 cancel `is` False cancel `is` False destroy wheel do putStrLn "Recurring timers work" ref <- newIORef (0::Int) wheel <- create Config { spokes = 4, resolution = 0.05 } recurring_ wheel (modifyIORef' ref (+1)) 0.15 sleep 1 readIORef ref `is` (6::Int) destroy wheel do putStrLn "Recurring timers can be canceled" ref <- newIORef (0::Int) wheel <- create Config { spokes = 4, resolution = 0.05 } cancel <- recurring wheel (modifyIORef' ref (+1)) 0.15 sleep 1 cancel sleep 1 readIORef ref `is` (6::Int) destroy wheel class Assert a b where is :: a -> b -> IO () instance (Eq a, Show a) => Assert (IO a) a where is mx y = do x <- mx unless (x == y) (throwIO (userError (show x ++ " /= " ++ show y))) sleep :: Fixed E6 -> IO () sleep (MkFixed micro) = threadDelay (fromIntegral micro)