Movatterモバイル変換
[0]ホーム
{-# 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' monadnewtypeIORefa=IORef(STRefRealWorlda)derivingEq-- ^ Pointer equality.---- @since 4.0.0.0-- |Build a new 'IORef'newIORef::a->IO(IORefa)newIORef :: 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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b>>=\STRef RealWorld avar->IORef a -> IO (IORef a)forall (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'readIORef::IORefa->IOareadIORef :: 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'writeIORef::IORefa->a->IO()writeIORef :: 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 :: 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 :: 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 (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 :: 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 (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_ :: 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'_ :: 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 (m :: * -> *) a. Monad m => a -> m areturn(aold,anew)-- | Atomically replace the contents of an 'IORef', returning-- the old contents.atomicSwapIORef::IORefa->a->IOa-- Bad implementation! This will be a primop shortly.atomicSwapIORef :: 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((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO aforall a b. (a -> b) -> a -> b$\State# RealWorlds->caseMutVar# RealWorld a-> (a -> Box a)-> State# RealWorld-> (# State# RealWorld, a, Box a #)forall d a c.MutVar# d a -> (a -> c) -> State# d -> (# State# d, a, c #)atomicModifyMutVar2#MutVar# RealWorld aref(\a_old->a -> Box aforall a. a -> Box aBoxanew)State# RealWorldsof(#State# RealWorlds',aold,Boxa_new#)->(#State# RealWorlds',aold#)dataBoxa=Boxa-- | Strict version of 'Data.IORef.atomicModifyIORef'. This forces both-- the value stored in the 'IORef' and the value returned. The new value-- is installed in the 'IORef' before the returned value is forced.-- So---- @atomicModifyIORef' ref (\x -> (x+1, undefined))@---- will increment the 'IORef' and then throw an exception in the calling-- thread.---- @since 4.6.0.0atomicModifyIORef'::IORefa->(a->(a,b))->IOb-- See Note [atomicModifyIORef' definition]atomicModifyIORef' :: 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 (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]ページ先頭