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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe