@@ -20,6 +20,7 @@ module Streamly.Internal.Data.Ring.Generic
21 -- * Conversion
21 -- * Conversion
22 , toMutArray
22 , toMutArray
23 , toStreamWith
24 , toStreamWith
@@ -29,15 +30,11 @@ import Control.Monad.IO.Class (liftIO, MonadIO)
29import Streamly.Internal.Data.Stream.Type (Stream)
30import Streamly.Internal.Data.Stream.Type (Stream)
30import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
31import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
31import Streamly.Internal.Data.Fold.Type (Fold(..))
32import Streamly.Internal.Data.Fold.Type (Fold(..))
32−import Streamly.Internal.Data.MutArray.Generic
33+import Streamly.Internal.Data.MutArray.Generic (MutArray(..))
39-- import qualified Streamly.Internal.Data.Stream.Type as Stream
35-- import qualified Streamly.Internal.Data.Stream.Type as Stream
40import qualified Streamly.Internal.Data.Fold.Type as Fold
36import qualified Streamly.Internal.Data.Fold.Type as Fold
37+import qualified Streamly.Internal.Data.MutArray.Generic as MutArray
42-- XXX Use MutableArray rather than keeping a MutArray here.
39-- XXX Use MutableArray rather than keeping a MutArray here.
43data Ring a = Ring
40data Ring a = Ring
@@ -58,8 +55,8 @@ data Ring a = Ring
58{-# INLINE createRing #-}
55{-# INLINE createRing #-}
59createRing :: MonadIO m => Int -> m (Ring a)
56createRing :: MonadIO m => Int -> m (Ring a)
60createRing count = liftIO $ do
57createRing count = liftIO $ do
61− arr <- new count
58+ arr <- MutArray.new count
62− arr1 <- uninit arr count
59+ arr1 <- MutArray.uninit arr count
63 return (Ring
60 return (Ring
64 { ringArr = arr1
61 { ringArr = arr1
65 , ringHead = 0
62 , ringHead = 0
@@ -67,6 +64,9 @@ createRing count = liftIO $ do
67+-- | Note that it is not safe to return a reference to the mutable Ring using a
68+-- scan as the Ring is continuously getting mutated. You could however copy out
70{-# INLINE writeLastN #-}
70{-# INLINE writeLastN #-}
71writeLastN :: MonadIO m => Int -> Fold m a (Ring a)
71writeLastN :: MonadIO m => Int -> Fold m a (Ring a)
72writeLastN n = Fold step initial extract
72writeLastN n = Fold step initial extract
@@ -101,7 +101,7 @@ unsafeInsertRingWith :: Ring a -> a -> IO Int
101unsafeInsertRingWith Ring{..} x = do
101unsafeInsertRingWith Ring{..} x = do
102 assertM(ringMax >= 1)
102 assertM(ringMax >= 1)
103 assertM(ringHead < ringMax)
103 assertM(ringHead < ringMax)
104− putIndexUnsafe ringHead ringArr x
104+ MutArray.putIndexUnsafe ringHead ringArr x
105 let rh1 = ringHead + 1
105 let rh1 = ringHead + 1
106 next = if rh1 == ringMax then 0 else rh1
106 next = if rh1 == ringMax then 0 else rh1
107 return next
107 return next
@@ -124,24 +124,45 @@ seek adj rng@Ring{..}
125-- | @toMutArray rignHeadAdjustment lengthToRead ring@.
125-- | @toMutArray rignHeadAdjustment lengthToRead ring@.
126-- Convert the ring into a boxed mutable array. Note that the returned MutArray
126-- Convert the ring into a boxed mutable array. Note that the returned MutArray
127−-- may share the same underlying memory as the Ring.
127+-- shares the same underlying memory as the Ring, the user of this API needs to
128+-- ensure that the ring is not mutated during and after the conversion.
128{-# INLINE toMutArray #-}
130{-# INLINE toMutArray #-}
129toMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
131toMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
130−toMutArray adj n Ring{..} = do
132+toMutArray adj n Ring{..} =
133+ -- XXX for empty Ring it will raise an Exception: divide by zero
131− let len = min ringMax n
137+ let len = min ringMax n
132− let idx = mod (ringHead + adj) ringMax
138+ let idx = mod (ringHead + adj) ringMax
133− end = idx + len
139+ end = idx + len
134− if end <= ringMax
140+ if end <= ringMax
136− -- putSliceUnsafe ringArr idx arr1 0 len
137− return $ ringArr { arrStart = idx, arrLen = len }
142+ return $ ringArr { arrStart = idx, arrLen = len }
144+ -- XXX Just swap the elements in the existing ring and return the
145+ -- same array without reallocation.
146+ arr <- liftIO $ MutArray.new len
147+ arr1 <- MutArray.uninit arr len
148+ MutArray.putSliceUnsafe ringArr idx arr1 0 (ringMax - idx)
149+ MutArray.putSliceUnsafe ringArr 0 arr1 (ringMax - idx) (end - ringMax)
152+-- | Copy out the mutable ring to a mutable Array.
153+{-# INLINE copyToMutArray #-}
154+copyToMutArray :: MonadIO m => Int -> Int -> Ring a -> m (MutArray a)
155+copyToMutArray adj n Ring{..} = do
139− -- XXX Just swap the elements in the existing ring and return the
159+ let len = min ringMax n
140− -- same array without reallocation.
160+ let idx = mod (ringHead + adj) ringMax
141− arr <- liftIO $ new len
162+ arr <- MutArray.new len
142− arr1 <- uninit arr len
163+ arr1 <- MutArray.uninit arr len
143− putSliceUnsafe ringArr idx arr1 0 (ringMax - idx)
164+ MutArray.putSliceUnsafe ringArr idx arr1 0 (ringMax - idx)
144− putSliceUnsafe ringArr 0 arr1 (ringMax - idx) (end - ringMax)
165+ MutArray.putSliceUnsafe ringArr 0 arr1 (ringMax - idx) (end - ringMax)
145 return arr1
166 return arr1
147-- This would be theoretically slower than toMutArray because of a branch
168-- This would be theoretically slower than toMutArray because of a branch