Other transactional arrays?

Currently, Haskell have transactional arrays in "Control.Concurrent.STM.TArray" implemented as "Array i (TVar e)" which is array of transactional variables. But what if I need to place an array into TVar itself? This is something like "TVar (IOArray i e)", but with ability to read/write array elements inside an STM transaction, and then commit changes with "atomically". I've tried to make up this arrays in the following way:
{-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# OPTIONS_GHC -fno-cse #-}
module Data.Vector.STM ( TVector , newTVector , newTVectorIO , readTVector , readTVectorIO , writeTVector ) where
import GHC.Conc import GHC.Prim import GHC.Types (Int(..), IO(..))
data MutableArray a = MutableArray (MutableArray# RealWorld a)
data TVector a = TVector (TVar# RealWorld (MutableArray a))
stm = STM {-# NOINLINE stm #-}
newTVector :: Int -> a -> STM (TVector a) newTVector (I# i#) x = stm $ \s1# -> case newArray# i# x s1# of { (# s2#, a# #) -> case newTVar# (MutableArray a#) s2# of { (# s3#, t# #) -> (# s3#, (TVector t#) #) }}
newTVectorIO :: Int -> a -> IO (TVector a) newTVectorIO (I# i#) x = IO $ \s1# -> case newArray# i# x s1# of { (# s2#, a# #) -> case newTVar# (MutableArray a#) s2# of { (# s3#, t# #) -> (# s3#, (TVector t#) #) }}
readTVector :: TVector a -> Int -> STM a readTVector (TVector t#) (I# i#) = stm $ \s1# -> case readTVar# t# s1# of { (# s2#, (MutableArray a#) #) -> case readArray# a# i# s2# of { (# s3#, a #) -> (# s3#, a #) }}
readTVectorIO :: TVector a -> Int -> IO a readTVectorIO (TVector t#) (I# i#) = IO $ \s1# -> case readTVarIO# t# s1# of { (# s2#, (MutableArray a#) #) -> case readArray# a# i# s2# of { (# s3#, a #) -> (# s3#, a #) }}
writeTVector :: TVector a -> Int -> a -> STM () writeTVector (TVector t#) (I# i#) x = stm $ \s1# -> case readTVar# t# s1# of { (# s2#, (MutableArray a#) #) -> case writeArray# a# i# x s2# of { s3# -> case writeTVar# t# (MutableArray a#) s3# of { s4# -> (# s4#, () #) }}}
It seems like it works, but I'm in doubt about it's correctness. Unfortunately, I don't know much about STM mechanics, so I'm asking Cafe users (you :-) for help.

On Fri, Jul 9, 2010 at 7:16 AM, Emil Melnicov
writeTVector :: TVector a -> Int -> a -> STM () writeTVector (TVector t#) (I# i#) x = stm $ \s1# -> case readTVar# t# s1# of { (# s2#, (MutableArray a#) #) -> case writeArray# a# i# x s2# of { s3# -> case writeTVar# t# (MutableArray a#) s3# of { s4# -> (# s4#, () #) }}}
It seems like it works, but I'm in doubt about it's correctness. Unfortunately, I don't know much about STM mechanics, so I'm asking Cafe users (you :-) for help.
I guess the only problem lies with writeTVector. I don't know much about STM implementation details as well, but reading the code for writeTVector I can't see how it could be rollbacked. I.e., should something with writeTVector fail and rollback, how will the old value get into the mutable array? Cheers :) -- Felipe.

On 9 July 2010, at 08:13
Felipe Lessa
I guess the only problem lies with writeTVector. I don't know much about STM implementation details as well, but reading the code for writeTVector I can't see how it could be rollbacked. I.e., should something with writeTVector fail and rollback, how will the old value get into the mutable array?
Cheers :)
-- Felipe.
Yes, you are right. We can't omit "writeArray#" here, and this one simply writes something to the array without any respect to transaction log. It seems that you can't fool Haskell's type system :) Actually, I can use "TVar (IntMap a)" to solve my problem. Nonetheless, I wonder if it is possible to access STM internals within Haskell (e.g. through some primitives like writeLog# or checkConsistency#), although it's hardly justified. -- Emil.
participants (2)
-
Emil Melnicov
-
Felipe Lessa