module Streamly.Internal.Data.Ring
( Ring(..)
, createRing
, unsafeInsertRing
) where
import Control.Monad.Primitive (PrimMonad(PrimState))
import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef, IORef)
import Data.Primitive.Array (newArray, writeArray, MutableArray)
data Ring a = Ring
{ Ring a -> MutableArray (PrimState IO) a
arr :: MutableArray (PrimState IO) a
, Ring a -> IORef Int
ringHead :: IORef Int
, Ring a -> Int
ringMax :: !Int
}
{-# INLINE createRing #-}
createRing :: Int -> IO (Ring a)
createRing :: Int -> IO (Ring a)
createRing Int
count = do
MutableArray RealWorld a
arr' <- Int -> a -> IO (MutableArray (PrimState IO) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (MutableArray (PrimState m) a)
newArray Int
count (forall a. a
forall a. HasCallStack => a
undefined :: a)
IORef Int
head' <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
Ring a -> IO (Ring a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Ring :: forall a.
MutableArray (PrimState IO) a -> IORef Int -> Int -> Ring a
Ring
{ arr :: MutableArray (PrimState IO) a
arr = MutableArray RealWorld a
MutableArray (PrimState IO) a
arr'
, ringHead :: IORef Int
ringHead = IORef Int
head'
, ringMax :: Int
ringMax = Int
count
})
{-# INLINE unsafeInsertRing #-}
unsafeInsertRing :: Ring a -> Int -> a -> IO ()
unsafeInsertRing :: Ring a -> Int -> a -> IO ()
unsafeInsertRing Ring{Int
IORef Int
MutableArray (PrimState IO) a
ringMax :: Int
ringHead :: IORef Int
arr :: MutableArray (PrimState IO) a
ringMax :: forall a. Ring a -> Int
ringHead :: forall a. Ring a -> IORef Int
arr :: forall a. Ring a -> MutableArray (PrimState IO) a
..} Int
idx a
x = do
MutableArray (PrimState IO) a -> Int -> a -> IO ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray (PrimState IO) a
arr (Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
idx Int
ringMax) a
x
Int
ref <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
ringHead
if (Int
refInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
ringMax
then IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Int
ringHead ( Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
else IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Int
ringHead Int
0