{-# LANGUAGE TypeFamilies #-} -- | Use 1-length mutable storable vectors for mutable references. -- -- Motivated by: and ArrayRef. module Data.Mutable.SRef ( -- * Types SRef , IOSRef -- * Functions , asSRef , MutableRef (..) ) where import Data.Mutable.Class import Foreign.ForeignPtr import Foreign.Storable import Control.Monad.Primitive -- | A storable vector reference, supporting any monad. -- -- Since 0.2.0 newtype SRef s a = SRef (ForeignPtr a) -- | -- Since 0.2.0 asSRef :: SRef s a -> SRef s a asSRef x = x {-# INLINE asSRef #-} -- | A storable IO vector reference. type IOSRef = SRef (PrimState IO) instance MutableContainer (SRef s a) where type MCState (SRef s a) = s instance Storable a => MutableRef (SRef s a) where type RefElement (SRef s a) = a newRef x = unsafePrimToPrim $ do fptr <- mallocForeignPtr withForeignPtr fptr $ flip poke x return $! SRef fptr {-# INLINE newRef#-} readRef (SRef fptr) = unsafePrimToPrim $ withForeignPtr fptr peek {-# INLINE readRef #-} writeRef (SRef fptr) x = unsafePrimToPrim $ withForeignPtr fptr $ flip poke x {-# INLINE writeRef #-} modifyRef (SRef fptr) f = unsafePrimToPrim $ withForeignPtr fptr $ \ptr -> peek ptr >>= poke ptr . f {-# INLINE modifyRef #-} modifyRef' = modifyRef {-# INLINE modifyRef' #-}