
On 14.12 23:07, Joel Reymont wrote:
Something like this? Comments are welcome!
timeout :: Int timeout = 5000000 -- 1 second
Is that correct?
{-# NOINLINE timers #-} timers :: MVar Timers timers = unsafePerformIO $ newMVar M.empty
--- Call this first initTimers :: IO () initTimers = do forkIO $ block checkTimers return ()
Here is a nice trick for you: {-# NOINLINE timers #-} timers :: MVar Timers timers = unsafePerformIO $ do mv <- newMVar M.empty forkIO $ block checkTimers return mv initTimers goes thus away.
--- Not sure if this is the most efficient way to do it startTimer :: String -> Int -> (IO ()) -> IO () startTimer name delay io = do stopTimer name now <- getClockTime let plus = TimeDiff 0 0 0 0 0 delay 0 future = addToClockTime plus now block $ do t <- takeMVar timers putMVar timers $ M.insert (future, name) io t
I had code which used a global IORef containing the current time. It was updated once by a second by a dedicated thread, but reading it was practically free. Depends how common getClockTime calls are.
--- The filter expression is kind of long... stopTimer :: String -> IO () stopTimer name = block $ do t <- takeMVar timers putMVar timers $ M.filterWithKey (\(_, k) _ -> k /= name) t
And slow. This is O(size_of_map)
--- Tried to take care of exceptions here --- but the code looks kind of ugly
Is there a reason you need block for checkTimers? What you certainly want to do is ignore exceptions from the timer actions. - Einar Karttunen