{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses #-} #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-} #endif ----------------------------------------------------------------------------- -- | -- Module : Control.Concurrent.STM.TArray -- Copyright : (c) The University of Glasgow 2005 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : non-portable (requires STM) -- -- TArrays: transactional arrays, for use in the STM monad -- ----------------------------------------------------------------------------- module Control.Concurrent.STM.TArray ( TArray ) where import Data.Array (Array, bounds) import Data.Array.Base (listArray, arrEleBottom, unsafeAt, MArray(..), IArray(numElements)) import Data.Ix (rangeSize) import Data.Typeable (Typeable) import Control.Concurrent.STM.TVar (TVar, newTVar, readTVar, writeTVar) #ifdef __GLASGOW_HASKELL__ import GHC.Conc (STM) #else import Control.Sequential.STM (STM) #endif -- |TArray is a transactional array, supporting the usual 'MArray' -- interface for mutable arrays. -- -- It is currently implemented as @Array ix (TVar e)@, -- but it may be replaced by a more efficient implementation in the future -- (the interface will remain the same, however). -- newtype TArray i e = TArray (Array i (TVar e)) deriving (Eq, Typeable) instance MArray TArray e STM where getBounds (TArray a) = return (bounds a) newArray b e = do a <- rep (rangeSize b) (newTVar e) return $ TArray (listArray b a) newArray_ b = do a <- rep (rangeSize b) (newTVar arrEleBottom) return $ TArray (listArray b a) unsafeRead (TArray a) i = readTVar $ unsafeAt a i unsafeWrite (TArray a) i e = writeTVar (unsafeAt a i) e getNumElements (TArray a) = return (numElements a) -- | Like 'replicateM' but uses an accumulator to prevent stack overflows. -- Unlike 'replicateM' the returned list is in reversed order. -- This doesn't matter though since this function is only used to create -- arrays with identical elements. rep :: Monad m => Int -> m a -> m [a] rep n m = go n [] where go 0 xs = return xs go i xs = do x <- m go (i-1) (x:xs)