[GHC] #10841: Run handler on STM retry

GHC ghc-devs at haskell.org
Wed Sep 9 13:09:53 UTC 2015


#10841: Run handler on STM retry
-------------------------------------+-------------------------------------
        Reporter:  shlevy            |                   Owner:
            Type:  feature request   |                  Status:  new
        Priority:  normal            |               Milestone:
       Component:  libraries         |                 Version:  7.10.2
  (other)                            |
      Resolution:                    |                Keywords:  stm
Operating System:  Unknown/Multiple  |            Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |               Test Case:
      Blocked By:                    |                Blocking:
 Related Tickets:                    |  Differential Revisions:
-------------------------------------+-------------------------------------

Comment (by fryguybob):

 Yes, the terminology is confusing.  There are things you can do inside the
 current STM to do this all at the user side (I didn't actually type check
 this):

 {{{#!hs
 atomicWithAbortPolicy :: Int -> IO (Maybe a) -> STM a -> IO a
 atomicWithAbortPolicy tryCount policy action = loop
   where
     loop :: IO a
     loop = do
       c <- newIORef 0 -- Thread local!
       res <- atomically $ do
         n <- unsafeIOToSTM $ readIORef c -- Thread local!
         if n > tryCount
            then return Nothing   -- Commit transaction nothing in the
 read-set, so it will
                                  -- always succeed.
            else do
               unsafeIOToSTM $ writeIORef (n + 1)  -- Thread local!
               Just <$> action
       case res of
         Just a  -> return a -- action succeeded
         Nothing -> policy >>= \case
                      Just a  -> return a  -- give up and return what
 policy gave.
                      Nothing -> loop      -- keep trying.
 }}}

 This is all completely safe as the `IORef` used never escapes.  Actions on
 the `IORef` are always performed at the beginning of the transaction.
 This will also enforce the policy for `retry`, though you really want to
 make that decision before blocking.  By wrapping `action` in `orElse` you
 can periodically commit `retry`ing transactions (discarding their effects)
 and run the policy outside of the transaction, loosing the more efficient
 wakeup.  But if you have some `tryCount` you get the best of both by
 getting the efficient wakeup some of the time, then giving up and doing
 something else.

 I have heard that there was a paper that sort of settles the topic of
 contention management in TM, I will look it up and see what it says.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10841#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list