{-# LANGUAGE GADTs#-}
module Data.HMemDb.References
    (CRef(CRef), Ref(Ref, refContent, refIndex),
     cRefIndex, deCRef, deRef, readCRef) where
import Control.Concurrent.STM (TVar, readTVar)
import Control.Monad.Trans.Maybe (MaybeT(MaybeT))
import Data.Function (on)
import Data.Map (Map)
import Data.HMemDb.MapTVar (MS, readTVarMap)
data Ref r = Ref {refContent :: TVar (Maybe r), refIndex :: Integer}
instance Eq (Ref r) where (==) = (==) `on` refIndex
instance Ord (Ref r) where compare = compare `on` refIndex
deRef :: Ref r -> MS r
deRef ref = MaybeT $ readTVar $ refContent ref
data CRef a where CRef :: Ref r -> (r -> MS a) -> CRef a
cRefIndex :: CRef a -> Integer
cRefIndex (CRef ref _) = refIndex ref
instance Eq (CRef a) where (==) = (==) `on` cRefIndex
instance Ord (CRef a) where compare = compare `on` cRefIndex
deCRef :: CRef a -> MS a
deCRef (CRef ref to) = deRef ref >>= to
readCRef :: (r -> MS a) -> TVar (Map Integer (TVar (Maybe r))) -> Integer -> MS (CRef a)
readCRef to tv i =
    do v <- readTVarMap tv i
       return $ CRef (Ref {refContent = v, refIndex = i}) to