2017-04-08 07:20:39 +03:00
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2016-06-06 00:25:46 +03:00
|
|
|
-- |
|
|
|
|
-- Module : Control.Concurrent.Classy.STM.
|
|
|
|
-- Copyright : (c) 2016 Michael Walker
|
|
|
|
-- License : MIT
|
|
|
|
-- Maintainer : Michael Walker <mike@barrucadu.co.uk>
|
|
|
|
-- Stability : stable
|
|
|
|
-- Portability : FlexibleInstances, MultiParamTypeClasses
|
|
|
|
--
|
|
|
|
-- TArrays: transactional arrays, for use in STM-like monads.
|
2016-04-03 08:56:26 +03:00
|
|
|
--
|
|
|
|
-- __Deviations:__ @TArray@ as defined here does not have an @Eq@
|
|
|
|
-- instance, this is because the @MonadSTM@ @TVar@ type does not have
|
|
|
|
-- an @Eq@ constraint.
|
2016-03-23 07:38:34 +03:00
|
|
|
module Control.Concurrent.Classy.STM.TArray (TArray) where
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2017-04-08 07:20:39 +03:00
|
|
|
import Data.Array (Array, bounds)
|
|
|
|
import Data.Array.Base (IArray(numElements), MArray(..),
|
|
|
|
arrEleBottom, listArray, unsafeAt)
|
|
|
|
import Data.Ix (rangeSize)
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2017-04-08 07:20:39 +03:00
|
|
|
import Control.Monad.STM.Class
|
2016-03-23 07:33:11 +03:00
|
|
|
|
|
|
|
-- | @TArray@ is a transactional array, supporting the usual 'MArray'
|
|
|
|
-- interface for mutable arrays.
|
|
|
|
--
|
|
|
|
-- It is currently implemented as @Array ix (TVar stm e)@, but it may
|
|
|
|
-- be replaced by a more efficient implementation in the future (the
|
|
|
|
-- interface will remain the same, however).
|
2017-04-05 23:25:02 +03:00
|
|
|
--
|
|
|
|
-- @since 1.0.0.0
|
2016-03-23 07:33:11 +03:00
|
|
|
newtype TArray stm i e = TArray (Array i (TVar stm e))
|
|
|
|
|
2017-04-05 23:25:02 +03:00
|
|
|
-- | @since 1.0.0.0
|
2016-03-23 07:33:11 +03:00
|
|
|
instance MonadSTM stm => MArray (TArray stm) e stm where
|
2016-03-26 09:26:28 +03:00
|
|
|
getBounds (TArray a) = pure (bounds a)
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2016-03-26 09:26:28 +03:00
|
|
|
newArray b e = do
|
|
|
|
a <- rep (rangeSize b) (newTVar e)
|
|
|
|
pure $ TArray (listArray b a)
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2016-03-26 09:26:28 +03:00
|
|
|
newArray_ b = newArray b arrEleBottom
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2016-03-26 09:26:28 +03:00
|
|
|
unsafeRead (TArray a) = readTVar . unsafeAt a
|
|
|
|
unsafeWrite (TArray a) = writeTVar . unsafeAt a
|
2016-03-23 07:33:11 +03:00
|
|
|
|
2016-03-26 09:26:28 +03:00
|
|
|
getNumElements (TArray a) = pure (numElements a)
|
2016-03-23 07:33:11 +03:00
|
|
|
|
|
|
|
-- | Like 'replicateM' but uses an accumulator to prevent stack overflows.
|
2016-03-23 07:38:34 +03:00
|
|
|
-- Unlike 'replicateM' the returned list is in reversed order. This
|
|
|
|
-- doesn't matter though since this function is only used to create
|
2016-03-23 07:33:11 +03:00
|
|
|
-- arrays with identical elements.
|
|
|
|
rep :: Monad m => Int -> m a -> m [a]
|
|
|
|
rep n m = go n [] where
|
|
|
|
go 0 xs = pure xs
|
|
|
|
go i xs = do
|
|
|
|
x <- m
|
|
|
|
go (i-1) (x:xs)
|