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