1module RIO.Prelude.URef 2 ( URef 3 , IOURef 4 , newURef 5 , readURef 6 , writeURef 7 , modifyURef 8 ) where 9 10import RIO.Prelude.Reexports 11import qualified Data.Vector.Unboxed.Mutable as MUVector 12 13-- | An unboxed reference. This works like an 'IORef', but the data is 14-- stored in a bytearray instead of a heap object, avoiding 15-- significant allocation overhead in some cases. For a concrete 16-- example, see this Stack Overflow question: 17-- <https://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes>. 18-- 19-- The first parameter is the state token type, the same as would be 20-- used for the 'ST' monad. If you're using an 'IO'-based monad, you 21-- can use the convenience 'IOURef' type synonym instead. 22-- 23-- @since 0.0.2.0 24newtype URef s a = URef (MUVector.MVector s a) 25 26-- | Helpful type synonym for using a 'URef' from an 'IO'-based stack. 27-- 28-- @since 0.0.2.0 29type IOURef = URef (PrimState IO) 30 31-- | Create a new 'URef' 32-- 33-- @since 0.0.2.0 34newURef :: (PrimMonad m, Unbox a) => a -> m (URef (PrimState m) a) 35newURef a = fmap URef (MUVector.replicate 1 a) 36 37-- | Read the value in a 'URef' 38-- 39-- @since 0.0.2.0 40readURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> m a 41readURef (URef v) = MUVector.unsafeRead v 0 42 43-- | Write a value into a 'URef'. Note that this action is strict, and 44-- will force evalution of the value. 45-- 46-- @since 0.0.2.0 47writeURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> a -> m () 48writeURef (URef v) = MUVector.unsafeWrite v 0 49 50-- | Modify a value in a 'URef'. Note that this action is strict, and 51-- will force evaluation of the result value. 52-- 53-- @since 0.0.2.0 54modifyURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> (a -> a) -> m () 55modifyURef u f = readURef u >>= writeURef u . f 56