import Control.Concurrent.Async (mapConcurrently)
import Data.Time.Clock.POSIX (getPOSIXTime)
import Data.Time (UTCTime)
import Control.Concurrent.STM (TMVar, atomically, takeTMVar, putTMVar, newTMVarIO)
import Data.List (nub)
getTime :: (Integral b, RealFrac a) => a -> IO b
getTime precision =
round . (* precision) . fromRational . toRational <$> getPOSIXTime
next :: Integral b => TMVar b -> IO b
next s = do
t <- getTime 1 -- one second precision
atomically $ do
v <- takeTMVar s
let t' = if t <= v then v + 1 else t
putTMVar s t'
return t'
main = do
next' <- next <$> newTMVarIO 0
res <- mapConcurrently id [next' | _ <- [1 .. 100]]
print $ length $ nub res