concurrency 1.5.0.0 → 1.6.0.0
raw patch · 6 files changed
+363/−171 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Concurrent.Classy.Async: instance (Control.Monad.Conc.Class.MonadConc m, Data.Semigroup.Semigroup a) => Data.Semigroup.Semigroup (Control.Concurrent.Classy.Async.Concurrently m a)
- Control.Monad.Conc.Class: atomicModifyCRef :: MonadConc m => CRef m a -> (a -> (a, b)) -> m b
- Control.Monad.Conc.Class: atomicWriteCRef :: MonadConc m => CRef m a -> a -> m ()
- Control.Monad.Conc.Class: casCRef :: MonadConc m => CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)
- Control.Monad.Conc.Class: modifyCRefCAS :: MonadConc m => CRef m a -> (a -> (a, b)) -> m b
- Control.Monad.Conc.Class: modifyCRefCAS_ :: MonadConc m => CRef m a -> (a -> a) -> m ()
- Control.Monad.Conc.Class: newCRef :: MonadConc m => a -> m (CRef m a)
- Control.Monad.Conc.Class: newCRefN :: MonadConc m => String -> a -> m (CRef m a)
- Control.Monad.Conc.Class: readCRef :: MonadConc m => CRef m a -> m a
- Control.Monad.Conc.Class: writeCRef :: MonadConc m => CRef m a -> a -> m ()
+ Control.Concurrent.Classy.Async: instance (Control.Monad.Conc.Class.MonadConc m, GHC.Base.Semigroup a) => GHC.Base.Semigroup (Control.Concurrent.Classy.Async.Concurrently m a)
+ Control.Concurrent.Classy.CRef: casCRef :: MonadConc m => CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)
+ Control.Concurrent.Classy.CRef: modifyCRefCAS :: MonadConc m => CRef m a -> (a -> (a, b)) -> m b
+ Control.Concurrent.Classy.CRef: modifyCRefCAS_ :: MonadConc m => CRef m a -> (a -> a) -> m ()
+ Control.Concurrent.Classy.CRef: newCRefN :: MonadConc m => String -> a -> m (CRef m a)
+ Control.Concurrent.Classy.CRef: type CRef m a = IORef m a
+ Control.Concurrent.Classy.IORef: atomicModifyIORef :: MonadConc m => IORef m a -> (a -> (a, b)) -> m b
+ Control.Concurrent.Classy.IORef: atomicModifyIORef' :: MonadConc m => IORef m a -> (a -> (a, b)) -> m b
+ Control.Concurrent.Classy.IORef: atomicWriteIORef :: MonadConc m => IORef m a -> a -> m ()
+ Control.Concurrent.Classy.IORef: modifyIORef :: MonadConc m => IORef m a -> (a -> a) -> m ()
+ Control.Concurrent.Classy.IORef: modifyIORef' :: MonadConc m => IORef m a -> (a -> a) -> m ()
+ Control.Concurrent.Classy.IORef: newIORef :: MonadConc m => a -> m (IORef m a)
+ Control.Concurrent.Classy.IORef: readIORef :: MonadConc m => IORef m a -> m a
+ Control.Concurrent.Classy.IORef: writeIORef :: MonadConc m => IORef m a -> a -> m ()
+ Control.Monad.Conc.Class: atomicModifyIORef :: MonadConc m => IORef m a -> (a -> (a, b)) -> m b
+ Control.Monad.Conc.Class: atomicWriteIORef :: MonadConc m => IORef m a -> a -> m ()
+ Control.Monad.Conc.Class: casIORef :: MonadConc m => IORef m a -> Ticket m a -> a -> m (Bool, Ticket m a)
+ Control.Monad.Conc.Class: modifyIORefCAS :: MonadConc m => IORef m a -> (a -> (a, b)) -> m b
+ Control.Monad.Conc.Class: modifyIORefCAS_ :: MonadConc m => IORef m a -> (a -> a) -> m ()
+ Control.Monad.Conc.Class: newIORef :: MonadConc m => a -> m (IORef m a)
+ Control.Monad.Conc.Class: newIORefN :: MonadConc m => String -> a -> m (IORef m a)
+ Control.Monad.Conc.Class: readIORef :: MonadConc m => IORef m a -> m a
+ Control.Monad.Conc.Class: writeIORef :: MonadConc m => IORef m a -> a -> m ()
- Control.Monad.Conc.Class: cas :: MonadConc m => CRef m a -> a -> m (Bool, a)
+ Control.Monad.Conc.Class: cas :: MonadConc m => IORef m a -> a -> m (Bool, a)
- Control.Monad.Conc.Class: readForCAS :: MonadConc m => CRef m a -> m (Ticket m a)
+ Control.Monad.Conc.Class: readForCAS :: MonadConc m => IORef m a -> m (Ticket m a)
Files
- CHANGELOG.rst +19/−0
- Control/Concurrent/Classy.hs +4/−0
- Control/Concurrent/Classy/CRef.hs +81/−33
- Control/Concurrent/Classy/IORef.hs +120/−0
- Control/Monad/Conc/Class.hs +136/−136
- concurrency.cabal +3/−2
CHANGELOG.rst view
@@ -7,6 +7,25 @@ .. _PVP: https://pvp.haskell.org/ +1.6.0.0 - IORefs (2018-07-01)+-----------------------------++* Git: :tag:`concurrency-1.6.0.0`+* Hackage: :hackage:`concurrency-1.6.0.0`++Added+~~~~~++* ``Control.Concurrent.Classy.CRef``, deprecated ``*CRef`` functions+ and a ``CRef`` alias.++Changed+~~~~~~~++* (:issue:`274`) ``CRef`` is now ``IORef``: all functions, modules,+ and types have been renamed.++ 1.5.0.0 - No More 7.10 (2018-03-28) -----------------------------------
Control/Concurrent/Classy.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -Wno-deprecations #-}+ -- | -- Module : Control.Concurrent.Classy -- Copyright : (c) 2016 Michael Walker@@ -23,6 +25,7 @@ ( module Control.Monad.Conc.Class , module Control.Concurrent.Classy.Chan , module Control.Concurrent.Classy.CRef+ , module Control.Concurrent.Classy.IORef , module Control.Concurrent.Classy.MVar , module Control.Concurrent.Classy.STM , module Control.Concurrent.Classy.QSem@@ -31,6 +34,7 @@ import Control.Concurrent.Classy.Chan import Control.Concurrent.Classy.CRef+import Control.Concurrent.Classy.IORef import Control.Concurrent.Classy.MVar import Control.Concurrent.Classy.QSem import Control.Concurrent.Classy.QSemN
Control/Concurrent/Classy/CRef.hs view
@@ -1,19 +1,18 @@ -- | -- Module : Control.Concurrent.Classy.CRef--- Copyright : (c) 2016 Michael Walker+-- Copyright : (c) 2016--2018 Michael Walker -- License : MIT -- Maintainer : Michael Walker <mike@barrucadu.co.uk>--- Stability : stable+-- Stability : experimental -- Portability : portable ----- Mutable references in a concurrency monad.------ __Deviations:__ There is no @Eq@ instance for @MonadConc@ the--- @CRef@ type. Furthermore, the @mkWeakIORef@ function is not--- provided.-module Control.Concurrent.Classy.CRef+-- Deprecated re-exports of @IORef@ functions under the old @CRef@+-- names.+module Control.Concurrent.Classy.CRef {-# DEPRECATED "Import Control.Concurrent.Classy.IORef instead" #-} ( -- * CRefs- newCRef+ CRef+ , newCRef+ , newCRefN , readCRef , writeCRef , modifyCRef@@ -22,6 +21,11 @@ , atomicModifyCRef' , atomicWriteCRef + -- ** Compare-and-swap+ , casCRef+ , modifyCRefCAS+ , modifyCRefCAS_+ -- * Memory Model -- | In a concurrent program, @CRef@ operations may appear@@ -80,41 +84,85 @@ -- memory barrier. ) where -import Control.Monad.Conc.Class+import qualified Control.Concurrent.Classy.IORef as IORef+import Control.Monad.Conc.Class (IORef, MonadConc, Ticket)+import qualified Control.Monad.Conc.Class as IORef +-- | Type alias for 'IORef'.+type CRef m a = IORef m a+{-# DEPRECATED CRef "Use IORef instead" #-}++-- | Create a new reference.+newCRef :: MonadConc m => a -> m (CRef m a)+newCRef = IORef.newIORef+{-# DEPRECATED newCRef "Use newIORef instead" #-}++-- | Create a new reference, but it is given a name which may be used+-- to present more useful debugging information.+newCRefN :: MonadConc m => String -> a -> m (CRef m a)+newCRefN = IORef.newIORefN+{-# DEPRECATED newCRefN "Use newIORefN instead" #-}++-- | Read the current value stored in a reference.+readCRef :: MonadConc m => CRef m a -> m a+readCRef = IORef.readIORef+{-# DEPRECATED readCRef "Use readIORef instead" #-}++-- | Write a new value into an @CRef@, without imposing a memory+-- barrier. This means that relaxed memory effects can be observed.+writeCRef :: MonadConc m => CRef m a -> a -> m ()+writeCRef = IORef.writeIORef+{-# DEPRECATED writeCRef "Use writeIORef instead" #-}+ -- | Mutate the contents of a @CRef@. -- -- Be warned that 'modifyCRef' does not apply the function strictly. -- This means if the program calls 'modifyCRef' many times, but -- seldomly uses the value, thunks will pile up in memory resulting in--- a space leak. This is a common mistake made when using a @CRef@ as--- a counter. For example, the following will likely produce a stack--- overflow:------ >ref <- newCRef 0--- >replicateM_ 1000000 $ modifyCRef ref (+1)--- >readCRef ref >>= print------ To avoid this problem, use 'modifyCRef'' instead.------ @since 1.0.0.0+-- a space leak. modifyCRef :: MonadConc m => CRef m a -> (a -> a) -> m ()-modifyCRef ref f = readCRef ref >>= writeCRef ref . f+modifyCRef = IORef.modifyIORef+{-# DEPRECATED modifyCRef "Use modifyIORef instead" #-} -- | Strict version of 'modifyCRef'------ @since 1.0.0.0 modifyCRef' :: MonadConc m => CRef m a -> (a -> a) -> m ()-modifyCRef' ref f = do- x <- readCRef ref- writeCRef ref $! f x+modifyCRef' = IORef.modifyIORef'+{-# DEPRECATED modifyCRef' "Use modifyIORef' instead" #-} +-- | Atomically modify the value stored in a reference. This imposes+-- a full memory barrier.+atomicModifyCRef :: MonadConc m => CRef m a -> (a -> (a, b)) -> m b+atomicModifyCRef = IORef.atomicModifyIORef+{-# DEPRECATED atomicModifyCRef "Use atomicModifyIORef instead" #-}+ -- | Strict version of 'atomicModifyCRef'. This forces both the value -- stored in the @CRef@ as well as the value returned.------ @since 1.0.0.0 atomicModifyCRef' :: MonadConc m => CRef m a -> (a -> (a,b)) -> m b-atomicModifyCRef' ref f = do- b <- atomicModifyCRef ref $ \a -> case f a of- v@(a',_) -> a' `seq` v- pure $! b+atomicModifyCRef' = IORef.atomicModifyIORef'+{-# DEPRECATED atomicModifyCRef' "Use atomicModifyIORef' instead" #-}++-- | Replace the value stored in a reference, with the+-- barrier-to-reordering property that 'atomicModifyIORef' has.+atomicWriteCRef :: MonadConc m => CRef m a -> a -> m ()+atomicWriteCRef = IORef.atomicWriteIORef+{-# DEPRECATED atomicWriteCRef "Use atomicWriteIORef instead" #-}++-- | Perform a machine-level compare-and-swap (CAS) operation on a+-- @CRef@. Returns an indication of success and a @Ticket@ for the+-- most current value in the @CRef@.+-- This is strict in the \"new\" value argument.+casCRef :: MonadConc m => CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)+casCRef = IORef.casIORef+{-# DEPRECATED casCRef "Use casIORef instead" #-}++-- | A replacement for 'atomicModifyCRef' using a compare-and-swap.+--+-- This is strict in the \"new\" value argument.+modifyCRefCAS :: MonadConc m => CRef m a -> (a -> (a, b)) -> m b+modifyCRefCAS = IORef.modifyIORefCAS+{-# DEPRECATED modifyCRefCAS "Use modifyIORefCAS instead" #-}++-- | A variant of 'modifyCRefCAS' which doesn't return a result.+modifyCRefCAS_ :: MonadConc m => CRef m a -> (a -> a) -> m ()+modifyCRefCAS_ = IORef.modifyIORefCAS_+{-# DEPRECATED modifyCRefCAS_ "Use modifyIORefCAS_ instead" #-}
+ Control/Concurrent/Classy/IORef.hs view
@@ -0,0 +1,120 @@+-- |+-- Module : Control.Concurrent.Classy.IORef+-- Copyright : (c) 2018 Michael Walker+-- License : MIT+-- Maintainer : Michael Walker <mike@barrucadu.co.uk>+-- Stability : stable+-- Portability : portable+--+-- Mutable references in a concurrency monad.+--+-- __Deviations:__ There is no @Eq@ instance for @MonadConc@ the+-- @IORef@ type. Furthermore, the @mkWeakIORef@ function is not+-- provided.+module Control.Concurrent.Classy.IORef+ ( -- * IORefs+ newIORef+ , readIORef+ , writeIORef+ , modifyIORef+ , modifyIORef'+ , atomicModifyIORef+ , atomicModifyIORef'+ , atomicWriteIORef++ -- * Memory Model++ -- | In a concurrent program, @IORef@ operations may appear+ -- out-of-order to another thread, depending on the memory model of+ -- the underlying processor architecture. For example, on x86 (which+ -- uses total store order), loads can move ahead of stores. Consider+ -- this example:+ --+ -- > iorefs :: MonadConc m => m (Bool, Bool)+ -- > iorefs = do+ -- > r1 <- newIORef False+ -- > r2 <- newIORef False+ -- >+ -- > x <- spawn $ writeIORef r1 True >> readIORef r2+ -- > y <- spawn $ writeIORef r2 True >> readIORef r1+ -- >+ -- > (,) <$> readMVar x <*> readMVar y+ --+ -- Under a sequentially consistent memory model the possible results+ -- are @(True, True)@, @(True, False)@, and @(False, True)@. Under+ -- total or partial store order, @(False, False)@ is also a possible+ -- result, even though there is no interleaving of the threads which+ -- can lead to this.+ --+ -- We can see this by testing with different memory models:+ --+ -- > > autocheckWay defaultWay SequentialConsistency relaxed+ -- > [pass] Never Deadlocks+ -- > [pass] No Exceptions+ -- > [fail] Consistent Result+ -- > (False,True) S0---------S1----S0--S2----S0--+ -- >+ -- > (True,True) S0---------S1-P2----S1---S0---+ -- >+ -- > (True,False) S0---------S2----S1----S0---+ -- > False+ --+ -- > > autocheckWay defaultWay TotalStoreOrder relaxed+ -- > [pass] Never Deadlocks+ -- > [pass] No Exceptions+ -- > [fail] Consistent Result+ -- > (False,True) S0---------S1----S0--S2----S0--+ -- >+ -- > (False,False) S0---------S1--P2----S1--S0---+ -- >+ -- > (True,False) S0---------S2----S1----S0---+ -- >+ -- > (True,True) S0---------S1-C-S2----S1---S0---+ -- > False+ --+ -- Traces for non-sequentially-consistent memory models show where+ -- writes to @IORef@s are /committed/, which makes a write visible to+ -- all threads rather than just the one which performed the+ -- write. Only 'writeIORef' is broken up into separate write and+ -- commit steps, 'atomicModifyIORef' is still atomic and imposes a+ -- memory barrier.+ ) where++import Control.Monad.Conc.Class++-- | Mutate the contents of a @IORef@.+--+-- Be warned that 'modifyIORef' does not apply the function strictly.+-- This means if the program calls 'modifyIORef' many times, but+-- seldomly uses the value, thunks will pile up in memory resulting in+-- a space leak. This is a common mistake made when using a @IORef@ as+-- a counter. For example, the following will likely produce a stack+-- overflow:+--+-- >ref <- newIORef 0+-- >replicateM_ 1000000 $ modifyIORef ref (+1)+-- >readIORef ref >>= print+--+-- To avoid this problem, use 'modifyIORef'' instead.+--+-- @since 1.6.0.0+modifyIORef :: MonadConc m => IORef m a -> (a -> a) -> m ()+modifyIORef ref f = readIORef ref >>= writeIORef ref . f++-- | Strict version of 'modifyIORef'+--+-- @since 1.6.0.0+modifyIORef' :: MonadConc m => IORef m a -> (a -> a) -> m ()+modifyIORef' ref f = do+ x <- readIORef ref+ writeIORef ref $! f x++-- | Strict version of 'atomicModifyIORef'. This forces both the value+-- stored in the @IORef@ as well as the value returned.+--+-- @since 1.6.0.0+atomicModifyIORef' :: MonadConc m => IORef m a -> (a -> (a,b)) -> m b+atomicModifyIORef' ref f = do+ b <- atomicModifyIORef ref $ \a -> case f a of+ v@(a',_) -> a' `seq` v+ pure $! b
Control/Monad/Conc/Class.hs view
@@ -8,7 +8,7 @@ -- | -- Module : Control.Monad.Conc.Class--- Copyright : (c) 2016--2017 Michael Walker+-- Copyright : (c) 2016--2018 Michael Walker -- License : MIT -- Maintainer : Michael Walker <mike@barrucadu.co.uk> -- Stability : experimental@@ -18,7 +18,7 @@ -- monads. -- -- __Deviations:__ An instance of @MonadConc@ is not required to be an--- instance of @MonadFix@, unlike @IO@. The @CRef@, @MVar@, and+-- instance of @MonadFix@, unlike @IO@. The @IORef@, @MVar@, and -- @Ticket@ types are not required to be instances of @Show@ or @Eq@, -- unlike their normal counterparts. The @threadCapability@, -- @threadWaitRead@, @threadWaitWrite@, @threadWaitReadSTM@,@@ -150,7 +150,7 @@ -- Do not be put off by the use of @UndecidableInstances@, it is safe -- here. ----- @since 1.5.0.0+-- @since 1.6.0.0 class ( Monad m , MonadCatch m, MonadThrow m, MonadMask m , MonadSTM (STM m)@@ -172,13 +172,13 @@ , tryReadMVar , takeMVar , tryTakeMVar- , (newCRef | newCRefN)- , atomicModifyCRef- , writeCRef+ , (newIORef | newIORefN)+ , atomicModifyIORef+ , writeIORef , readForCAS , peekTicket'- , casCRef- , modifyCRefCAS+ , casIORef+ , modifyIORefCAS , atomically , throwTo #-}@@ -197,13 +197,13 @@ type MVar m :: * -> * -- | The mutable non-blocking reference type. These may suffer from- -- relaxed memory effects if functions outside the set @newCRef@,- -- @readCRef@, @atomicModifyCRef@, and @atomicWriteCRef@ are used.+ -- relaxed memory effects if functions outside the set @newIORef@,+ -- @readIORef@, @atomicModifyIORef@, and @atomicWriteIORef@ are used. --- -- @since 1.0.0.0- type CRef m :: * -> *+ -- @since 1.6.0.0+ type IORef m :: * -> * - -- | When performing compare-and-swap operations on @CRef@s, a+ -- | When performing compare-and-swap operations on @IORef@s, a -- @Ticket@ is a proof that a thread observed a specific previous -- value. --@@ -376,55 +376,55 @@ -- | Create a new reference. --- -- > newCRef = newCRefN ""+ -- > newIORef = newIORefN "" --- -- @since 1.0.0.0- newCRef :: a -> m (CRef m a)- newCRef = newCRefN ""+ -- @since 1.6.0.0+ newIORef :: a -> m (IORef m a)+ newIORef = newIORefN "" -- | Create a new reference, but it is given a name which may be -- used to present more useful debugging information. --- -- > newCRefN _ = newCRef+ -- > newIORefN _ = newIORef --- -- @since 1.0.0.0- newCRefN :: String -> a -> m (CRef m a)- newCRefN _ = newCRef+ -- @since 1.6.0.0+ newIORefN :: String -> a -> m (IORef m a)+ newIORefN _ = newIORef -- | Read the current value stored in a reference. --- -- > readCRef cref = readForCAS cref >>= peekTicket+ -- > readIORef ioref = readForCAS ioref >>= peekTicket --- -- @since 1.0.0.0- readCRef :: CRef m a -> m a- readCRef cref = readForCAS cref >>= peekTicket+ -- @since 1.6.0.0+ readIORef :: IORef m a -> m a+ readIORef ioref = readForCAS ioref >>= peekTicket -- | Atomically modify the value stored in a reference. This imposes -- a full memory barrier. --- -- @since 1.0.0.0- atomicModifyCRef :: CRef m a -> (a -> (a, b)) -> m b+ -- @since 1.6.0.0+ atomicModifyIORef :: IORef m a -> (a -> (a, b)) -> m b - -- | Write a new value into an @CRef@, without imposing a memory+ -- | Write a new value into an @IORef@, without imposing a memory -- barrier. This means that relaxed memory effects can be observed. --- -- @since 1.0.0.0- writeCRef :: CRef m a -> a -> m ()+ -- @since 1.6.0.0+ writeIORef :: IORef m a -> a -> m () -- | Replace the value stored in a reference, with the- -- barrier-to-reordering property that 'atomicModifyCRef' has.+ -- barrier-to-reordering property that 'atomicModifyIORef' has. --- -- > atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())+ -- > atomicWriteIORef r a = atomicModifyIORef r $ const (a, ()) --- -- @since 1.0.0.0- atomicWriteCRef :: CRef m a -> a -> m ()- atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())+ -- @since 1.6.0.0+ atomicWriteIORef :: IORef m a -> a -> m ()+ atomicWriteIORef r a = atomicModifyIORef r $ const (a, ()) -- | Read the current value stored in a reference, returning a -- @Ticket@, for use in future compare-and-swap operations. --- -- @since 1.0.0.0- readForCAS :: CRef m a -> m (Ticket m a)+ -- @since 1.6.0.0+ readForCAS :: IORef m a -> m (Ticket m a) -- | Extract the actual Haskell value from a @Ticket@. --@@ -434,28 +434,28 @@ peekTicket' :: Proxy m -> Ticket m a -> a -- | Perform a machine-level compare-and-swap (CAS) operation on a- -- @CRef@. Returns an indication of success and a @Ticket@ for the- -- most current value in the @CRef@.+ -- @IORef@. Returns an indication of success and a @Ticket@ for the+ -- most current value in the @IORef@. -- -- This is strict in the \"new\" value argument. --- -- @since 1.0.0.0- casCRef :: CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)+ -- @since 1.6.0.0+ casIORef :: IORef m a -> Ticket m a -> a -> m (Bool, Ticket m a) - -- | A replacement for 'atomicModifyCRef' using a compare-and-swap.+ -- | A replacement for 'atomicModifyIORef' using a compare-and-swap. -- -- This is strict in the \"new\" value argument. --- -- @since 1.0.0.0- modifyCRefCAS :: CRef m a -> (a -> (a, b)) -> m b+ -- @since 1.6.0.0+ modifyIORefCAS :: IORef m a -> (a -> (a, b)) -> m b - -- | A variant of 'modifyCRefCAS' which doesn't return a result.+ -- | A variant of 'modifyIORefCAS' which doesn't return a result. --- -- > modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))+ -- > modifyIORefCAS_ ioref f = modifyIORefCAS ioref (\a -> (f a, ())) --- -- @since 1.0.0.0- modifyCRefCAS_ :: CRef m a -> (a -> a) -> m ()- modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))+ -- @since 1.6.0.0+ modifyIORefCAS_ :: IORef m a -> (a -> a) -> m ()+ modifyIORefCAS_ ioref f = modifyIORefCAS ioref (\a -> (f a, ())) -- | Perform an STM transaction atomically. --@@ -687,14 +687,14 @@ peekTicket :: forall m a. MonadConc m => Ticket m a -> m a peekTicket t = pure $ peekTicket' (Proxy :: Proxy m) (t :: Ticket m a) --- | Compare-and-swap a value in a @CRef@, returning an indication of+-- | Compare-and-swap a value in a @IORef@, returning an indication of -- success and the new value. ----- @since 1.0.0.0-cas :: MonadConc m => CRef m a -> a -> m (Bool, a)-cas cref a = do- tick <- readForCAS cref- (suc, tick') <- casCRef cref tick a+-- @since 1.6.0.0+cas :: MonadConc m => IORef m a -> a -> m (Bool, a)+cas ioref a = do+ tick <- readForCAS ioref+ (suc, tick') <- casIORef ioref tick a a' <- peekTicket tick' pure (suc, a')@@ -706,7 +706,7 @@ instance MonadConc IO where type STM IO = IO.STM type MVar IO = IO.MVar- type CRef IO = IO.IORef+ type IORef IO = IO.IORef type Ticket IO = IO.Ticket type ThreadId IO = IO.ThreadId @@ -728,30 +728,30 @@ isCurrentThreadBound = IO.isCurrentThreadBound - getNumCapabilities = IO.getNumCapabilities- setNumCapabilities = IO.setNumCapabilities- readMVar = IO.readMVar- tryReadMVar = IO.tryReadMVar- myThreadId = IO.myThreadId- yield = IO.yield- threadDelay = IO.threadDelay- throwTo = IO.throwTo- newEmptyMVar = IO.newEmptyMVar- putMVar = IO.putMVar- tryPutMVar = IO.tryPutMVar- takeMVar = IO.takeMVar- tryTakeMVar = IO.tryTakeMVar- newCRef = IO.newIORef- readCRef = IO.readIORef- atomicModifyCRef = IO.atomicModifyIORef- writeCRef = IO.writeIORef- atomicWriteCRef = IO.atomicWriteIORef- readForCAS = IO.readForCAS- peekTicket' _ = IO.peekTicket- casCRef = IO.casIORef- modifyCRefCAS = IO.atomicModifyIORefCAS- atomically = IO.atomically- readTVarConc = IO.readTVarIO+ getNumCapabilities = IO.getNumCapabilities+ setNumCapabilities = IO.setNumCapabilities+ readMVar = IO.readMVar+ tryReadMVar = IO.tryReadMVar+ myThreadId = IO.myThreadId+ yield = IO.yield+ threadDelay = IO.threadDelay+ throwTo = IO.throwTo+ newEmptyMVar = IO.newEmptyMVar+ putMVar = IO.putMVar+ tryPutMVar = IO.tryPutMVar+ takeMVar = IO.takeMVar+ tryTakeMVar = IO.tryTakeMVar+ newIORef = IO.newIORef+ readIORef = IO.readIORef+ atomicModifyIORef = IO.atomicModifyIORef+ writeIORef = IO.writeIORef+ atomicWriteIORef = IO.atomicWriteIORef+ readForCAS = IO.readForCAS+ peekTicket' _ = IO.peekTicket+ casIORef = IO.casIORef+ modifyIORefCAS = IO.atomicModifyIORefCAS+ atomically = IO.atomically+ readTVarConc = IO.readTVarIO -- | Label the current thread, if the given label is nonempty. labelMe :: String -> IO ()@@ -786,7 +786,7 @@ instance MonadConc m => MonadConc (IsConc m) where type STM (IsConc m) = IsSTM (STM m) type MVar (IsConc m) = MVar m- type CRef (IsConc m) = CRef m+ type IORef (IsConc m) = IORef m type Ticket (IsConc m) = Ticket m type ThreadId (IsConc m) = ThreadId m @@ -799,33 +799,33 @@ isCurrentThreadBound = toIsConc isCurrentThreadBound - getNumCapabilities = toIsConc getNumCapabilities- setNumCapabilities = toIsConc . setNumCapabilities- myThreadId = toIsConc myThreadId- yield = toIsConc yield- threadDelay = toIsConc . threadDelay- throwTo t = toIsConc . throwTo t- newEmptyMVar = toIsConc newEmptyMVar- newEmptyMVarN = toIsConc . newEmptyMVarN- readMVar = toIsConc . readMVar- tryReadMVar = toIsConc . tryReadMVar- putMVar v = toIsConc . putMVar v- tryPutMVar v = toIsConc . tryPutMVar v- takeMVar = toIsConc . takeMVar- tryTakeMVar = toIsConc . tryTakeMVar- newCRef = toIsConc . newCRef- newCRefN n = toIsConc . newCRefN n- readCRef = toIsConc . readCRef- atomicModifyCRef r = toIsConc . atomicModifyCRef r- writeCRef r = toIsConc . writeCRef r- atomicWriteCRef r = toIsConc . atomicWriteCRef r- readForCAS = toIsConc . readForCAS- peekTicket' _ = peekTicket' (Proxy :: Proxy m)- casCRef r t = toIsConc . casCRef r t- modifyCRefCAS r = toIsConc . modifyCRefCAS r- modifyCRefCAS_ r = toIsConc . modifyCRefCAS_ r- atomically = toIsConc . atomically . fromIsSTM- readTVarConc = toIsConc . readTVarConc+ getNumCapabilities = toIsConc getNumCapabilities+ setNumCapabilities = toIsConc . setNumCapabilities+ myThreadId = toIsConc myThreadId+ yield = toIsConc yield+ threadDelay = toIsConc . threadDelay+ throwTo t = toIsConc . throwTo t+ newEmptyMVar = toIsConc newEmptyMVar+ newEmptyMVarN = toIsConc . newEmptyMVarN+ readMVar = toIsConc . readMVar+ tryReadMVar = toIsConc . tryReadMVar+ putMVar v = toIsConc . putMVar v+ tryPutMVar v = toIsConc . tryPutMVar v+ takeMVar = toIsConc . takeMVar+ tryTakeMVar = toIsConc . tryTakeMVar+ newIORef = toIsConc . newIORef+ newIORefN n = toIsConc . newIORefN n+ readIORef = toIsConc . readIORef+ atomicModifyIORef r = toIsConc . atomicModifyIORef r+ writeIORef r = toIsConc . writeIORef r+ atomicWriteIORef r = toIsConc . atomicWriteIORef r+ readForCAS = toIsConc . readForCAS+ peekTicket' _ = peekTicket' (Proxy :: Proxy m)+ casIORef r t = toIsConc . casIORef r t+ modifyIORefCAS r = toIsConc . modifyIORefCAS r+ modifyIORefCAS_ r = toIsConc . modifyIORefCAS_ r+ atomically = toIsConc . atomically . fromIsSTM+ readTVarConc = toIsConc . readTVarConc ------------------------------------------------------------------------------- -- Transformer instances@@ -834,7 +834,7 @@ instance C => MonadConc (T m) where { \ type STM (T m) = STM m ; \ type MVar (T m) = MVar m ; \- type CRef (T m) = CRef m ; \+ type IORef (T m) = IORef m ; \ type Ticket (T m) = Ticket m ; \ type ThreadId (T m) = ThreadId m ; \ \@@ -847,33 +847,33 @@ \ isCurrentThreadBound = lift isCurrentThreadBound ; \ \- getNumCapabilities = lift getNumCapabilities ; \- setNumCapabilities = lift . setNumCapabilities ; \- myThreadId = lift myThreadId ; \- yield = lift yield ; \- threadDelay = lift . threadDelay ; \- throwTo t = lift . throwTo t ; \- newEmptyMVar = lift newEmptyMVar ; \- newEmptyMVarN = lift . newEmptyMVarN ; \- readMVar = lift . readMVar ; \- tryReadMVar = lift . tryReadMVar ; \- putMVar v = lift . putMVar v ; \- tryPutMVar v = lift . tryPutMVar v ; \- takeMVar = lift . takeMVar ; \- tryTakeMVar = lift . tryTakeMVar ; \- newCRef = lift . newCRef ; \- newCRefN n = lift . newCRefN n ; \- readCRef = lift . readCRef ; \- atomicModifyCRef r = lift . atomicModifyCRef r ; \- writeCRef r = lift . writeCRef r ; \- atomicWriteCRef r = lift . atomicWriteCRef r ; \- readForCAS = lift . readForCAS ; \- peekTicket' _ = peekTicket' (Proxy :: Proxy m) ; \- casCRef r t = lift . casCRef r t ; \- modifyCRefCAS r = lift . modifyCRefCAS r ; \- modifyCRefCAS_ r = lift . modifyCRefCAS_ r ; \- atomically = lift . atomically ; \- readTVarConc = lift . readTVarConc }+ getNumCapabilities = lift getNumCapabilities ; \+ setNumCapabilities = lift . setNumCapabilities ; \+ myThreadId = lift myThreadId ; \+ yield = lift yield ; \+ threadDelay = lift . threadDelay ; \+ throwTo t = lift . throwTo t ; \+ newEmptyMVar = lift newEmptyMVar ; \+ newEmptyMVarN = lift . newEmptyMVarN ; \+ readMVar = lift . readMVar ; \+ tryReadMVar = lift . tryReadMVar ; \+ putMVar v = lift . putMVar v ; \+ tryPutMVar v = lift . tryPutMVar v ; \+ takeMVar = lift . takeMVar ; \+ tryTakeMVar = lift . tryTakeMVar ; \+ newIORef = lift . newIORef ; \+ newIORefN n = lift . newIORefN n ; \+ readIORef = lift . readIORef ; \+ atomicModifyIORef r = lift . atomicModifyIORef r ; \+ writeIORef r = lift . writeIORef r ; \+ atomicWriteIORef r = lift . atomicWriteIORef r ; \+ readForCAS = lift . readForCAS ; \+ peekTicket' _ = peekTicket' (Proxy :: Proxy m) ; \+ casIORef r t = lift . casIORef r t ; \+ modifyIORefCAS r = lift . modifyIORefCAS r ; \+ modifyIORefCAS_ r = lift . modifyIORefCAS_ r ; \+ atomically = lift . atomically ; \+ readTVarConc = lift . readTVarConc } -- | New threads inherit the reader state of their parent, but do not -- communicate results back.
concurrency.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: concurrency-version: 1.5.0.0+version: 1.6.0.0 synopsis: Typeclasses, functions, and data types for concurrency and STM. description:@@ -32,7 +32,7 @@ source-repository this type: git location: https://github.com/barrucadu/dejafu.git- tag: concurrency-1.5.0.0+ tag: concurrency-1.6.0.0 library exposed-modules: Control.Monad.Conc.Class@@ -42,6 +42,7 @@ , Control.Concurrent.Classy.Async , Control.Concurrent.Classy.Chan , Control.Concurrent.Classy.CRef+ , Control.Concurrent.Classy.IORef , Control.Concurrent.Classy.MVar , Control.Concurrent.Classy.QSem , Control.Concurrent.Classy.QSemN