@@ -98,14 +98,14 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
98 -- ** To streams
98 -- ** To streams
99 , ReadUState(..)
99 , ReadUState(..)
101− , readRev_
101+ , readRevWith
102 , readRev
102 , readRev
104 -- ** To containers
104 -- ** To containers
105− , toStreamD_
105+ , toStreamDWith
106− , toStreamDRev_
106+ , toStreamDRevWith
107− , toStreamK_
107+ , toStreamKWith
108− , toStreamKRev_
108+ , toStreamKRevWith
109 , toStreamD
109 , toStreamD
110 , toStreamDRev
110 , toStreamDRev
111 , toStreamK
111 , toStreamK
@@ -113,6 +113,7 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
115 -- experimental
115 -- experimental
116 , producer
117 , producer
118 -- ** Random reads
119 -- ** Random reads
@@ -203,6 +204,10 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
208+-- When we use a purely lazy Monad like Identity, we need to force ordering of
209+-- some actions for correctness.
206#include "inline.hs"
211#include "inline.hs"
207#include "ArrayMacros.h"
212#include "ArrayMacros.h"
208#include "MachDeps.h"
213#include "MachDeps.h"
@@ -1516,24 +1521,36 @@ data ReadUState a = ReadUState
1516toReadUState :: Array a -> ReadUState a
1521toReadUState :: Array a -> ReadUState a
1517toReadUState (Array contents start end _) = ReadUState contents end start
1522toReadUState (Array contents start end _) = ReadUState contents end start
1519−-- | Resumable unfold of an array.
1521−{-# INLINE_NORMAL producer #-}
1524+{-# INLINE_NORMAL producerWith #-}
1522−producer :: forall m a. (MonadIO m, Storable a) => Producer m (Array a) a
1526+ forall m a. (Monad m, Storable a)
1527+ => (forall b. IO b -> m b) -> Producer m (Array a) a
1523−producer = Producer step (return . toReadUState) extract
1528+producerWith liftio = Producer step (return . toReadUState) extract
1526 {-# INLINE_LATE step #-}
1531 {-# INLINE_LATE step #-}
1527 step (ReadUState contents end cur)
1532 step (ReadUState contents end cur)
1528− | assert (cur <= end) (cur == end) = do
1533+ | assert (cur <= end) (cur == end) = liftio $ do
1534+ -- We bind it strictly here as we don't want this to be optimized
1535+ -- out in a purely lazy monad like Identity.
1529− liftIO $ touch contents
1536+ !_ <- touch contents
1530 return D.Stop
1537 return D.Stop
1531 step (ReadUState contents end cur) = do
1538 step (ReadUState contents end cur) = do
1539+ -- When we use a purely lazy Monad like Identity, we need to force a
1540+ -- few actions for correctness and execution order sanity. We want
1541+ -- the peek to occur right here and not lazily at some later point
1542+ -- because we want the peek to be ordered with respect to the touch.
1532− !x <- liftIO $ peek cur
1543+ !x <- liftio $ peek cur
1533 return $ D.Yield x (ReadUState contents end (PTR_NEXT(cur,a)))
1544 return $ D.Yield x (ReadUState contents end (PTR_NEXT(cur,a)))
1535 extract (ReadUState contents end cur) = return $ Array contents cur end end
1546 extract (ReadUState contents end cur) = return $ Array contents cur end end
1548+-- | Resumable unfold of an array.
1550+{-# INLINE_NORMAL producer #-}
1551+producer :: forall m a. (MonadIO m, Storable a) => Producer m (Array a) a
1552+producer = producerWith liftIO
1537-- | Unfold an array into a stream.
1554-- | Unfold an array into a stream.
1539-- @since 0.7.0
1556-- @since 0.7.0
@@ -1541,11 +1558,11 @@ producer = Producer step (return . toReadUState) extract
1541read :: forall m a. (MonadIO m, Storable a) => Unfold m (Array a) a
1558read :: forall m a. (MonadIO m, Storable a) => Unfold m (Array a) a
1542read = Producer.simplify producer
1559read = Producer.simplify producer
1544−{-# INLINE_NORMAL readRev_ #-}
1561+{-# INLINE_NORMAL readRevWith #-}
1545−readRev_ ::
1562+readRevWith ::
1546 forall m a. (Monad m, Storable a)
1563 forall m a. (Monad m, Storable a)
1547 => (forall b. IO b -> m b) -> Unfold m (Array a) a
1564 => (forall b. IO b -> m b) -> Unfold m (Array a) a
1548−readRev_ liftio = Unfold step inject
1565+readRevWith liftio = Unfold step inject
1551 inject (Array contents start end _) =
1568 inject (Array contents start end _) =
@@ -1553,16 +1570,11 @@ readRev_ liftio = Unfold step inject
1553 in return $ ReadUState contents start p
1570 in return $ ReadUState contents start p
1555 {-# INLINE_LATE step #-}
1572 {-# INLINE_LATE step #-}
1556− step (ReadUState contents start p) | p < start = do
1573+ step (ReadUState contents start p) | p < start = liftio $ do
1557− -- Is the following replicated properly?
1558− -- let x = unsafeInlineIO $ touch contents
1559− -- in x `seq` return D.Stop
1560− liftio $ touch contents
1574+ !_ <- touch contents
1561 return D.Stop
1575 return D.Stop
1562− -- unit <- liftio $ touch contents
1563− -- unit `seq` return D.Stop
1564 step (ReadUState contents start p) = do
1576 step (ReadUState contents start p) = do
1565− x <- liftio $ peek p
1577+ !x <- liftio $ peek p
1566 return $ D.Yield x (ReadUState contents start (PTR_PREV(p,a)))
1578 return $ D.Yield x (ReadUState contents start (PTR_PREV(p,a)))
1568-- | Unfold an array into a stream in reverse order.
1580-- | Unfold an array into a stream in reverse order.
@@ -1570,7 +1582,7 @@ readRev_ liftio = Unfold step inject
1570-- /Pre-release/
1582-- /Pre-release/
1571{-# INLINE_NORMAL readRev #-}
1583{-# INLINE_NORMAL readRev #-}
1572readRev :: forall m a. (MonadIO m, Storable a) => Unfold m (Array a) a
1584readRev :: forall m a. (MonadIO m, Storable a) => Unfold m (Array a) a
1573−readRev = readRev_ liftIO
1585+readRev = readRevWith liftIO
1575-------------------------------------------------------------------------------
1587-------------------------------------------------------------------------------
1576-- to Lists and streams
1588-- to Lists and streams
@@ -1616,11 +1628,11 @@ toList Array{..} = liftIO $ go arrStart
1616 touch arrContents
1628 touch arrContents
1617 (:) x <$> go (PTR_NEXT(p,a))
1629 (:) x <$> go (PTR_NEXT(p,a))
1619−{-# INLINE_NORMAL toStreamD_ #-}
1631+{-# INLINE_NORMAL toStreamDWith #-}
1620−toStreamD_ ::
1632+toStreamDWith ::
1621 forall m a. (Monad m, Storable a)
1633 forall m a. (Monad m, Storable a)
1622 => (forall b. IO b -> m b) -> Array a -> D.Stream m a
1634 => (forall b. IO b -> m b) -> Array a -> D.Stream m a
1623−toStreamD_ liftio Array{..} = D.Stream step arrStart
1635+toStreamDWith liftio Array{..} = D.Stream step arrStart
@@ -1638,13 +1650,13 @@ toStreamD_ liftio Array{..} = D.Stream step arrStart
1638-- We can try this if the unfold has any performance issues.
1650-- We can try this if the unfold has any performance issues.
1639{-# INLINE_NORMAL toStreamD #-}
1651{-# INLINE_NORMAL toStreamD #-}
1640toStreamD :: forall m a. (MonadIO m, Storable a) => Array a -> D.Stream m a
1652toStreamD :: forall m a. (MonadIO m, Storable a) => Array a -> D.Stream m a
1641−toStreamD arr = toStreamD_ liftIO arr
1653+toStreamD = toStreamDWith liftIO
1643−{-# INLINE toStreamK_ #-}
1655+{-# INLINE toStreamKWith #-}
1644−toStreamK_ ::
1656+toStreamKWith ::
1645 forall m a. (Monad m, Storable a)
1657 forall m a. (Monad m, Storable a)
1646 => (forall b. IO b -> m b) -> Array a -> K.Stream m a
1658 => (forall b. IO b -> m b) -> Array a -> K.Stream m a
1647−toStreamK_ liftio Array{..} = go arrStart
1659+toStreamKWith liftio Array{..} = go arrStart
@@ -1658,13 +1670,13 @@ toStreamK_ liftio Array{..} = go arrStart
1659{-# INLINE toStreamK #-}
1671{-# INLINE toStreamK #-}
1660toStreamK :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
1672toStreamK :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
1661−toStreamK arr = toStreamK_ liftIO arr
1673+toStreamK = toStreamKWith liftIO
1663−{-# INLINE_NORMAL toStreamDRev_ #-}
1675+{-# INLINE_NORMAL toStreamDRevWith #-}
1664−toStreamDRev_ ::
1676+toStreamDRevWith ::
1665 forall m a. (Monad m, Storable a)
1677 forall m a. (Monad m, Storable a)
1666 => (forall b. IO b -> m b) -> Array a -> D.Stream m a
1678 => (forall b. IO b -> m b) -> Array a -> D.Stream m a
1667−toStreamDRev_ liftio Array{..} =
1679+toStreamDRevWith liftio Array{..} =
1668 let p = PTR_PREV(aEnd,a)
1680 let p = PTR_PREV(aEnd,a)
1669 in D.Stream step p
1681 in D.Stream step p
@@ -1684,13 +1696,13 @@ toStreamDRev_ liftio Array{..} =
1684-- We can try this if the unfold has any perf issues.
1696-- We can try this if the unfold has any perf issues.
1685{-# INLINE_NORMAL toStreamDRev #-}
1697{-# INLINE_NORMAL toStreamDRev #-}
1686toStreamDRev :: forall m a. (MonadIO m, Storable a) => Array a -> D.Stream m a
1698toStreamDRev :: forall m a. (MonadIO m, Storable a) => Array a -> D.Stream m a
1687−toStreamDRev arr = toStreamDRev_ liftIO arr
1699+toStreamDRev = toStreamDRevWith liftIO
1689−{-# INLINE toStreamKRev_ #-}
1701+{-# INLINE toStreamKRevWith #-}
1690−toStreamKRev_ ::
1702+toStreamKRevWith ::
1691 forall m a. (Monad m, Storable a)
1703 forall m a. (Monad m, Storable a)
1692 => (forall b. IO b -> m b) -> Array a -> K.Stream m a
1704 => (forall b. IO b -> m b) -> Array a -> K.Stream m a
1693−toStreamKRev_ liftio Array {..} =
1705+toStreamKRevWith liftio Array {..} =
1694 let p = PTR_PREV(aEnd,a)
1706 let p = PTR_PREV(aEnd,a)
@@ -1706,7 +1718,7 @@ toStreamKRev_ liftio Array {..} =
1707{-# INLINE toStreamKRev #-}
1719{-# INLINE toStreamKRev #-}
1708toStreamKRev :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
1720toStreamKRev :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
1709−toStreamKRev arr = toStreamKRev_ liftIO arr
1721+toStreamKRev = toStreamKRevWith liftIO
1711-------------------------------------------------------------------------------
1723-------------------------------------------------------------------------------
1712-- Folding
1724-- Folding