module Main where
import Control.Concurrent
import Control.Concurrent.STM
import Control.Event
import Text.Printf (printf)
import Data.Time
import Data.Time.Clock.POSIX
singleTimeout :: NominalDiffTime -> IO ()
singleTimeout secs = do
sys <- initEventSystem
a <- atomically $ newTVar 0
startTime <- getPOSIXTime
now <- getCurrentTime
let newSec = truncate secs
newPS = truncate $ 10^12 * (secs - (fromIntegral newSec))
addEvent sys (addUTCTime secs now) (getPOSIXTime >>= atomically . writeTVar a)
endTime <- atomically (do
t <- readTVar a
if t == 0
then retry
else return t)
printf "%dms sleep took: %s\n" ((truncate $ secs * 1000) :: Int) (show (endTime - startTime))
multiTimeout :: Int -> NominalDiffTime -> IO ()
multiTimeout n secs = do
sys <- initEventSystem
a <- atomically $ newTVar n
now <- getCurrentTime
startTime <- getPOSIXTime
mapM_ (const $ addEvent sys (addUTCTime secs now) (decAndPrint a)) [1..n]
atomically (do
n' <- readTVar a
if n' == 0
then return ()
else retry )
endTime <- getPOSIXTime
printf "%d timeouts for %d ms took %s\n" n ((truncate $ secs * 1000) :: Int) (show $ endTime - startTime)
where
decAndPrint :: TVar Int -> IO ()
decAndPrint a =
atomically (do
n <- readTVar a
writeTVar a (n - 1) )
setAndCancelTimeout :: Int -> NominalDiffTime -> IO ()
setAndCancelTimeout n secs = do
sys <- initEventSystem
a <- atomically $ newTVar (0 :: Int)
now <- getCurrentTime
startTime <- getPOSIXTime
tags <- mapM (const $ addEvent sys (addUTCTime secs now) (atomically $ readTVar a >>= writeTVar a . ((+) 1))) [1..n]
mapM (cancelEvent sys) tags
endTime <- getPOSIXTime
expired <- atomically $ readTVar a
printf "Setting and killing %d timeouts for %d ms took %s and %d expired\n" n ((truncate $ secs * 1000) :: Int) (show $ endTime - startTime) expired
main = do
sequence [singleTimeout 0, singleTimeout 0.1, singleTimeout 0.5, singleTimeout 1.0]
sequence [multiTimeout 10 0.1, multiTimeout 100 0.1, multiTimeout 1000 0.1, multiTimeout 10000 0.1]
sequence [setAndCancelTimeout 10 0.1, setAndCancelTimeout 100 0.1, setAndCancelTimeout 1000 0.1, setAndCancelTimeout 10000 0.1, setAndCancelTimeout 100000 0.1]
return ()