Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE Unsafe #-}{-# LANGUAGE NoImplicitPrelude, MagicHash #-}{-# LANGUAGE UnboxedTuples #-}{-# LANGUAGE BangPatterns #-}{-# OPTIONS_HADDOCK not-home #-}------------------------------------------------------------------------------- |-- Module      :  GHC.IORef-- Copyright   :  (c) The University of Glasgow 2008-- License     :  see libraries/base/LICENSE---- Maintainer  :  cvs-ghc@haskell.org-- Stability   :  internal-- Portability :  non-portable (GHC Extensions)---- The IORef type-------------------------------------------------------------------------------moduleGHC.IORef(IORef(..),newIORef,readIORef,writeIORef,atomicModifyIORef2Lazy,atomicModifyIORef2,atomicModifyIORefLazy_,atomicModifyIORef'_,atomicModifyIORefP,atomicSwapIORef,atomicModifyIORef')whereimportGHC.BaseimportGHC.STRefimportGHC.IO-- ----------------------------------------------------------------------------- IORefs-- |A mutable variable in the 'IO' monad.---- >>> import Data.IORef-- >>> r <- newIORef 0-- >>> readIORef r-- 0-- >>> writeIORef r 1-- >>> readIORef r-- 1-- >>> atomicWriteIORef r 2-- >>> readIORef r-- 2-- >>> modifyIORef' r (+ 1)-- >>> readIORef r-- 3-- >>> atomicModifyIORef' r (\a -> (a + 1, ()))-- >>> readIORef r-- 4---- See also 'Data.STRef.STRef' and 'Control.Concurrent.MVar.MVar'.--newtypeIORefa=IORef(STRefRealWorlda)derivingIORef a -> IORef a -> Bool(IORef a -> IORef a -> Bool)-> (IORef a -> IORef a -> Bool) -> Eq (IORef a)forall a. IORef a -> IORef a -> Boolforall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a$c== :: forall a. IORef a -> IORef a -> Bool== :: IORef a -> IORef a -> Bool$c/= :: forall a. IORef a -> IORef a -> Bool/= :: IORef a -> IORef a -> BoolEq-- ^ Pointer equality.---- @since 4.0.0.0-- |Build a new 'IORef'newIORef::a->IO(IORefa)newIORef :: forall a. a -> IO (IORef a)newIORefav=ST RealWorld (STRef RealWorld a) -> IO (STRef RealWorld a)forall a. ST RealWorld a -> IO astToIO(a -> ST RealWorld (STRef RealWorld a)forall a s. a -> ST s (STRef s a)newSTRefav)IO (STRef RealWorld a)-> (STRef RealWorld a -> IO (IORef a)) -> IO (IORef a)forall a b. IO a -> (a -> IO b) -> IO bforall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b>>=\STRef RealWorld avar->IORef a -> IO (IORef a)forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(STRef RealWorld a -> IORef aforall a. STRef RealWorld a -> IORef aIORefSTRef RealWorld avar)-- |Read the value of an 'IORef'.---- Beware that the CPU executing a thread can reorder reads or writes-- to independent locations. See "Data.IORef#memmodel" for more details.readIORef::IORefa->IOareadIORef :: forall a. IORef a -> IO areadIORef(IORefSTRef RealWorld avar)=ST RealWorld a -> IO aforall a. ST RealWorld a -> IO astToIO(STRef RealWorld a -> ST RealWorld aforall s a. STRef s a -> ST s areadSTRefSTRef RealWorld avar)-- |Write a new value into an 'IORef'.---- This function does not create a memory barrier and can be reordered-- with other independent reads and writes within a thread, which may cause issues-- for multithreaded execution. In these cases, consider using 'Data.IORef.atomicWriteIORef'-- instead. See "Data.IORef#memmodel" for more details.writeIORef::IORefa->a->IO()writeIORef :: forall a. IORef a -> a -> IO ()writeIORef(IORefSTRef RealWorld avar)av=ST RealWorld () -> IO ()forall a. ST RealWorld a -> IO astToIO(STRef RealWorld a -> a -> ST RealWorld ()forall s a. STRef s a -> a -> ST s ()writeSTRefSTRef RealWorld avarav)-- | Atomically apply a function to the contents of an 'IORef',-- installing its first component in the 'IORef' and returning-- the old contents and the result of applying the function.-- The result of the function application (the pair) is not forced.-- As a result, this can lead to memory leaks. It is generally better-- to use 'atomicModifyIORef2'.atomicModifyIORef2Lazy::IORefa->(a->(a,b))->IO(a,(a,b))atomicModifyIORef2Lazy :: forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))atomicModifyIORef2Lazy(IORef(STRefMutVar# RealWorld ar#))a -> (a, b)f=(State# RealWorld -> (# State# RealWorld, (a, (a, b)) #))-> IO (a, (a, b))forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO(\State# RealWorlds->caseMutVar# RealWorld a-> (a -> (a, b))-> State# RealWorld-> (# State# RealWorld, a, (a, b) #)forall d a c.MutVar# d a -> (a -> c) -> State# d -> (# State# d, a, c #)atomicModifyMutVar2#MutVar# RealWorld ar#a -> (a, b)fState# RealWorldsof(#State# RealWorlds',aold,(a, b)res#)->(#State# RealWorlds',(aold,(a, b)res)#))-- | Atomically apply a function to the contents of an 'IORef',-- installing its first component in the 'IORef' and returning-- the old contents and the result of applying the function.-- The result of the function application (the pair) is forced,-- but neither of its components is.atomicModifyIORef2::IORefa->(a->(a,b))->IO(a,(a,b))atomicModifyIORef2 :: forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))atomicModifyIORef2IORef arefa -> (a, b)f=dor :: (a, (a, b))r@(a_old,(a_new,b_res))<-IORef a -> (a -> (a, b)) -> IO (a, (a, b))forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))atomicModifyIORef2LazyIORef arefa -> (a, b)f(a, (a, b)) -> IO (a, (a, b))forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(a, (a, b))r-- | A version of 'Data.IORef.atomicModifyIORef' that forces-- the (pair) result of the function.atomicModifyIORefP::IORefa->(a->(a,b))->IObatomicModifyIORefP :: forall a b. IORef a -> (a -> (a, b)) -> IO batomicModifyIORefPIORef arefa -> (a, b)f=do(a_old,(a_,br))<-IORef a -> (a -> (a, b)) -> IO (a, (a, b))forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))atomicModifyIORef2IORef arefa -> (a, b)fb -> IO bforall a. a -> IO aforall (f :: * -> *) a. Applicative f => a -> f apurebr-- | Atomically apply a function to the contents of an-- 'IORef' and return the old and new values. The result-- of the function is not forced. As this can lead to a-- memory leak, it is usually better to use `atomicModifyIORef'_`.atomicModifyIORefLazy_::IORefa->(a->a)->IO(a,a)atomicModifyIORefLazy_ :: forall a. IORef a -> (a -> a) -> IO (a, a)atomicModifyIORefLazy_(IORef(STRefMutVar# RealWorld aref))a -> af=(State# RealWorld -> (# State# RealWorld, (a, a) #)) -> IO (a, a)forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO((State# RealWorld -> (# State# RealWorld, (a, a) #)) -> IO (a, a))-> (State# RealWorld -> (# State# RealWorld, (a, a) #))-> IO (a, a)forall a b. (a -> b) -> a -> b$\State# RealWorlds->caseMutVar# RealWorld a-> (a -> a) -> State# RealWorld -> (# State# RealWorld, a, a #)forall d a.MutVar# d a -> (a -> a) -> State# d -> (# State# d, a, a #)atomicModifyMutVar_#MutVar# RealWorld arefa -> afState# RealWorldsof(#State# RealWorlds',aold,anew#)->(#State# RealWorlds',(aold,anew)#)-- | Atomically apply a function to the contents of an-- 'IORef' and return the old and new values. The result-- of the function is forced.atomicModifyIORef'_::IORefa->(a->a)->IO(a,a)atomicModifyIORef'_ :: forall a. IORef a -> (a -> a) -> IO (a, a)atomicModifyIORef'_IORef arefa -> af=do(aold,!anew)<-IORef a -> (a -> a) -> IO (a, a)forall a. IORef a -> (a -> a) -> IO (a, a)atomicModifyIORefLazy_IORef arefa -> af(a, a) -> IO (a, a)forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(aold,anew)-- | Atomically replace the contents of an 'IORef', returning-- the old contents.atomicSwapIORef::IORefa->a->IOaatomicSwapIORef :: forall a. IORef a -> a -> IO aatomicSwapIORef(IORef(STRefMutVar# RealWorld aref))anew=(State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO aIO(MutVar# RealWorld a-> a -> State# RealWorld -> (# State# RealWorld, a #)forall d a. MutVar# d a -> a -> State# d -> (# State# d, a #)atomicSwapMutVar#MutVar# RealWorld arefanew)-- | A strict version of 'Data.IORef.atomicModifyIORef'.  This forces both the-- value stored in the 'IORef' and the value returned.---- Conceptually,---- @-- atomicModifyIORef' ref f = do--   -- Begin atomic block--   old <- 'readIORef' ref--   let r = f old--       new = fst r--   'writeIORef' ref new--   -- End atomic block--   case r of--     (!_new, !res) -> pure res-- @---- The actions in the \"atomic block\" are not subject to interference-- by other threads. In particular, the value in the 'IORef' cannot-- change between the 'readIORef' and 'writeIORef' invocations.---- The new value is installed in the 'IORef' before either value is forced.-- So---- @atomicModifyIORef' ref (\x -> (x+1, undefined))@---- will increment the 'IORef' and then throw an exception in the calling-- thread.---- @atomicModifyIORef' ref (\x -> (undefined, x))@---- and---- @atomicModifyIORef' ref (\_ -> undefined)@---- will each raise an exception in the calling thread, but will /also/-- install the bottoming value in the 'IORef', where it may be read by-- other threads.---- This function imposes a memory barrier, preventing reordering around-- the \"atomic block\"; see "Data.IORef#memmodel" for details.---- @since 4.6.0.0atomicModifyIORef'::IORefa->(a->(a,b))->IOb-- See Note [atomicModifyIORef' definition]atomicModifyIORef' :: forall a b. IORef a -> (a -> (a, b)) -> IO batomicModifyIORef'IORef arefa -> (a, b)f=do(a_old,(a_new,!bres))<-IORef a -> (a -> (a, b)) -> IO (a, (a, b))forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))atomicModifyIORef2IORef aref((a -> (a, b)) -> IO (a, (a, b)))-> (a -> (a, b)) -> IO (a, (a, b))forall a b. (a -> b) -> a -> b$\aold->casea -> (a, b)faoldofr :: (a, b)r@(!a_new,b_res)->(a, b)rb -> IO bforall a. a -> IO aforall (f :: * -> *) a. Applicative f => a -> f apurebres-- Note [atomicModifyIORef' definition]-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-- atomicModifyIORef' was historically defined----    atomicModifyIORef' ref f = do--        b <- atomicModifyIORef ref $ \a ->--                case f a of--                    v@(a',_) -> a' `seq` v--        b `seq` return b---- The most obvious definition, now that we have atomicModifyMutVar2#,-- would be----    atomicModifyIORef' ref f = do--      (_old, (!_new, !res)) <- atomicModifyIORef2 ref f--      pure res---- Why do we force the new value on the "inside" instead of afterwards?-- I initially thought the latter would be okay, but then I realized-- that if we write----   atomicModifyIORef' ref $ \x -> (x + 5, x - 5)---- then we'll end up building a pair of thunks to calculate x + 5-- and x - 5. That's no good! With the more complicated definition,-- we avoid this problem; the result pair is strict in the new IORef-- contents. Of course, if the function passed to atomicModifyIORef'-- doesn't inline, we'll build a closure for it. But that was already-- true for the historical definition of atomicModifyIORef' (in terms-- of atomicModifyIORef), so we shouldn't lose anything. Note that-- in keeping with the historical behavior, we *don't* propagate the-- strict demand on the result inwards. In particular,----   atomicModifyIORef' ref (\x -> (x + 1, undefined))---- will increment the IORef and throw an exception; it will not-- install an undefined value in the IORef.---- A clearer version, in my opinion (but one quite incompatible with-- the traditional one) would only force the new IORef value and not-- the result. This version would have been relatively inefficient-- to implement using atomicModifyMutVar#, but is just fine now.

[8]ページ先頭

©2009-2025 Movatter.jp