module Data.RRBVector.Internal.IntRef
    ( IntRef
    , newIntRef
    , readIntRef
    , writeIntRef
    , modifyIntRef
    ) where

import Control.Monad.ST
import Data.Primitive.PrimArray

newtype IntRef s = IntRef (MutablePrimArray s Int)

newIntRef :: Int -> ST s (IntRef s)
newIntRef :: Int -> ST s (IntRef s)
newIntRef Int
i = do
    MutablePrimArray s Int
arr <- Int -> ST s (MutablePrimArray (PrimState (ST s)) Int)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MutablePrimArray (PrimState m) a)
newPrimArray Int
1
    MutablePrimArray (PrimState (ST s)) Int
-> Int -> Int -> Int -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> Int -> a -> m ()
setPrimArray MutablePrimArray s Int
MutablePrimArray (PrimState (ST s)) Int
arr Int
0 Int
1 Int
i
    IntRef s -> ST s (IntRef s)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MutablePrimArray s Int -> IntRef s
forall s. MutablePrimArray s Int -> IntRef s
IntRef MutablePrimArray s Int
arr)
{-# INLINE newIntRef #-}

readIntRef :: IntRef s -> ST s Int
readIntRef :: IntRef s -> ST s Int
readIntRef (IntRef MutablePrimArray s Int
arr) = MutablePrimArray (PrimState (ST s)) Int -> Int -> ST s Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Int
MutablePrimArray (PrimState (ST s)) Int
arr Int
0
{-# INLINE readIntRef #-}

writeIntRef :: IntRef s -> Int -> ST s ()
writeIntRef :: IntRef s -> Int -> ST s ()
writeIntRef (IntRef MutablePrimArray s Int
arr) = MutablePrimArray (PrimState (ST s)) Int -> Int -> Int -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Int
MutablePrimArray (PrimState (ST s)) Int
arr Int
0
{-# INLINE writeIntRef #-}

modifyIntRef :: IntRef s -> (Int -> Int) -> ST s ()
modifyIntRef :: IntRef s -> (Int -> Int) -> ST s ()
modifyIntRef (IntRef MutablePrimArray s Int
arr) Int -> Int
f = do
    Int
i <- MutablePrimArray (PrimState (ST s)) Int -> Int -> ST s Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Int
MutablePrimArray (PrimState (ST s)) Int
arr Int
0
    MutablePrimArray (PrimState (ST s)) Int -> Int -> Int -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Int
MutablePrimArray (PrimState (ST s)) Int
arr Int
0 (Int -> Int
f Int
i)
{-# INLINE modifyIntRef #-}