[commit: base] master: IO manager: Edit the timeout queue directly, rather than using an edit list (e843e73)
Johan Tibell
johan.tibell at gmail.com
Sun Jun 9 00:08:55 CEST 2013
Is this related to some bug? The edit list was there for a reason. :)
On Jun 8, 2013 1:19 PM, "Ian Lynagh" <igloo at earth.li> wrote:
> Repository : ssh://darcs.haskell.org//srv/darcs/packages/base
>
> On branch : master
>
>
> https://github.com/ghc/packages-base/commit/e843e73690f828498f6e33bb89f47a50c3ab2ac9
>
> >---------------------------------------------------------------
>
> commit e843e73690f828498f6e33bb89f47a50c3ab2ac9
> Author: Ian Lynagh <ian at well-typed.com>
> Date: Sat Jun 8 20:19:59 2013 +0100
>
> IO manager: Edit the timeout queue directly, rather than using an edit
> list
>
> Fixes #7653.
>
> >---------------------------------------------------------------
>
> GHC/Event/TimerManager.hs | 61
> +++++++++++++++++++++-----------------------
> 1 files changed, 29 insertions(+), 32 deletions(-)
>
> diff --git a/GHC/Event/TimerManager.hs b/GHC/Event/TimerManager.hs
> index b581891..453f2eb 100644
> --- a/GHC/Event/TimerManager.hs
> +++ b/GHC/Event/TimerManager.hs
> @@ -39,7 +39,7 @@ module GHC.Event.TimerManager
>
> import Control.Exception (finally)
> import Control.Monad ((=<<), liftM, sequence_, when)
> -import Data.IORef (IORef, atomicModifyIORef, mkWeakIORef, newIORef,
> readIORef,
> +import Data.IORef (IORef, atomicModifyIORef, atomicModifyIORef',
> mkWeakIORef, newIORef, readIORef,
> writeIORef)
> import Data.Maybe (Maybe(..))
> import Data.Monoid (mempty)
> @@ -114,7 +114,7 @@ type TimeoutEdit = TimeoutQueue -> TimeoutQueue
> -- | The event manager state.
> data TimerManager = TimerManager
> { emBackend :: !Backend
> - , emTimeouts :: {-# UNPACK #-} !(IORef TimeoutEdit)
> + , emTimeouts :: {-# UNPACK #-} !(IORef TimeoutQueue)
> , emState :: {-# UNPACK #-} !(IORef State)
> , emUniqueSource :: {-# UNPACK #-} !UniqueSource
> , emControl :: {-# UNPACK #-} !Control
> @@ -144,7 +144,7 @@ new = newWith =<< newDefaultBackend
>
> newWith :: Backend -> IO TimerManager
> newWith be = do
> - timeouts <- newIORef id
> + timeouts <- newIORef Q.empty
> ctrl <- newControl True
> state <- newIORef Created
> us <- newSource
> @@ -192,38 +192,39 @@ loop mgr = do
> Created -> (Running, s)
> _ -> (s, s)
> case state of
> - Created -> go Q.empty `finally` cleanup mgr
> + Created -> go `finally` cleanup mgr
> Dying -> cleanup mgr
> _ -> do cleanup mgr
> error $ "GHC.Event.Manager.loop: state is already " ++
> show state
> where
> - go q = do (running, q') <- step mgr q
> - when running $ go q'
> + go = do running <- step mgr
> + when running go
>
> -step :: TimerManager -> TimeoutQueue -> IO (Bool, TimeoutQueue)
> -step mgr tq = do
> - (timeout, q') <- mkTimeout tq
> +step :: TimerManager -> IO Bool
> +step mgr = do
> + timeout <- mkTimeout
> _ <- I.poll (emBackend mgr) (Just timeout) (handleControlEvent mgr)
> state <- readIORef (emState mgr)
> - state `seq` return (state == Running, q')
> + state `seq` return (state == Running)
> where
>
> -- | Call all expired timer callbacks and return the time to the
> -- next timeout.
> - mkTimeout :: TimeoutQueue -> IO (Timeout, TimeoutQueue)
> - mkTimeout q = do
> + mkTimeout :: IO Timeout
> + mkTimeout = do
> now <- getMonotonicTime
> - applyEdits <- atomicModifyIORef (emTimeouts mgr) $ \f -> (id, f)
> - let (expired, q'') = let q' = applyEdits q in q' `seq` Q.atMost now
> q'
> + (expired, timeout) <- atomicModifyIORef (emTimeouts mgr) $ \tq ->
> + let (expired, tq') = Q.atMost now tq
> + timeout = case Q.minView tq' of
> + Nothing -> Forever
> + Just (Q.E _ t _, _) ->
> + -- This value will always be positive since the call
> + -- to 'atMost' above removed any timeouts <= 'now'
> + let t' = t - now in t' `seq` Timeout t'
> + in (tq', (expired, timeout))
> sequence_ $ map Q.value expired
> - let timeout = case Q.minView q'' of
> - Nothing -> Forever
> - Just (Q.E _ t _, _) ->
> - -- This value will always be positive since the call
> - -- to 'atMost' above removed any timeouts <= 'now'
> - let t' = t - now in t' `seq` Timeout t'
> - return (timeout, q'')
> + return timeout
>
> -- | Wake up the event manager.
> wakeManager :: TimerManager -> IO ()
> @@ -244,21 +245,14 @@ registerTimeout mgr us cb = do
> now <- getMonotonicTime
> let expTime = fromIntegral us / 1000000.0 + now
>
> - -- We intentionally do not evaluate the modified map to WHNF here.
> - -- Instead, we leave a thunk inside the IORef and defer its
> - -- evaluation until mkTimeout in the event loop. This is a
> - -- workaround for a nasty IORef contention problem that causes the
> - -- thread-delay benchmark to take 20 seconds instead of 0.2.
> - atomicModifyIORef (emTimeouts mgr) $ \f ->
> - let f' = (Q.insert key expTime cb) . f in (f', ())
> + editTimeouts mgr (Q.insert key expTime cb)
> wakeManager mgr
> return $ TK key
>
> -- | Unregister an active timeout.
> unregisterTimeout :: TimerManager -> TimeoutKey -> IO ()
> unregisterTimeout mgr (TK key) = do
> - atomicModifyIORef (emTimeouts mgr) $ \f ->
> - let f' = (Q.delete key) . f in (f', ())
> + editTimeouts mgr (Q.delete key)
> wakeManager mgr
>
> -- | Update an active timeout to fire in the given number of
> @@ -268,6 +262,9 @@ updateTimeout mgr (TK key) us = do
> now <- getMonotonicTime
> let expTime = fromIntegral us / 1000000.0 + now
>
> - atomicModifyIORef (emTimeouts mgr) $ \f ->
> - let f' = (Q.adjust (const expTime) key) . f in (f', ())
> + editTimeouts mgr (Q.adjust (const expTime) key)
> wakeManager mgr
> +
> +editTimeouts :: TimerManager -> TimeoutEdit -> IO ()
> +editTimeouts mgr g = atomicModifyIORef' (emTimeouts mgr) $ \tq -> (g tq,
> ())
> +
>
>
>
> _______________________________________________
> ghc-commits mailing list
> ghc-commits at haskell.org
> http://www.haskell.org/mailman/listinfo/ghc-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/ghc-devs/attachments/20130608/060ca87b/attachment.htm>
More information about the ghc-devs
mailing list