@@ -93,6 +93,9 @@ module Streamly.Internal.Data.Stream.StreamD
93 , enumerateFromToFractional
93 , enumerateFromToFractional
94 , enumerateFromThenToFractional
94 , enumerateFromThenToFractional
96 -- ** Conversions
99 -- ** Conversions
97 -- | Transform an input structure into a stream.
100 -- | Transform an input structure into a stream.
98 -- | Direct style stream does not support @fromFoldable@.
101 -- | Direct style stream does not support @fromFoldable@.
@@ -245,9 +248,11 @@ module Streamly.Internal.Data.Stream.StreamD
245 , filterM
248 , filterM
248 , takeWhile
252 , takeWhile
249 , takeWhileM
253 , takeWhileM
251 , dropWhile
256 , dropWhile
252 , dropWhileM
257 , dropWhileM
@@ -307,18 +312,13 @@ module Streamly.Internal.Data.Stream.StreamD
307 , mkParallelD
312 , mkParallelD
318import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
318import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
319import Control.Exception
319import Control.Exception
320 (Exception, SomeException, AsyncException, fromException)
320 (Exception, SomeException, AsyncException, fromException)
321−import Control.Monad (void, when)
321+import Control.Monad (void, when, forever)
322import Control.Monad.Catch (MonadCatch, throwM)
322import Control.Monad.Catch (MonadCatch, throwM)
323import Control.Monad.IO.Class (MonadIO(..))
323import Control.Monad.IO.Class (MonadIO(..))
324import Control.Monad.Reader (ReaderT)
324import Control.Monad.Reader (ReaderT)
@@ -327,6 +327,7 @@ import Control.Monad.Trans (MonadTrans(lift))
327import Control.Monad.Trans.Control (MonadBaseControl)
327import Control.Monad.Trans.Control (MonadBaseControl)
328import Data.Bits (shiftR, shiftL, (.|.), (.&.))
328import Data.Bits (shiftR, shiftL, (.|.), (.&.))
329import Data.Functor.Identity (Identity(..))
329import Data.Functor.Identity (Identity(..))
330+import Data.Int (Int64)
330import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
331import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
331import Data.Maybe (fromJust, isJust, isNothing)
332import Data.Maybe (fromJust, isJust, isNothing)
332import Data.Word (Word32)
333import Data.Word (Word32)
@@ -346,7 +347,6 @@ import qualified Control.Monad.Reader as Reader
346import qualified Control.Monad.State.Strict as State
347import qualified Control.Monad.State.Strict as State
347import qualified Prelude
348import qualified Prelude
349−import Data.Int (Int64)
350import Streamly.Internal.Mutable.Prim.Var
350import Streamly.Internal.Mutable.Prim.Var
351 (Prim, Var, readVar, newVar, modifyVar')
351 (Prim, Var, readVar, newVar, modifyVar')
352import Streamly.Internal.Data.Time.Units
352import Streamly.Internal.Data.Time.Units
@@ -357,7 +357,8 @@ import Streamly.Internal.Memory.Array.Types (Array(..))
357import Streamly.Internal.Data.Fold.Types (Fold(..))
357import Streamly.Internal.Data.Fold.Types (Fold(..))
358import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
358import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
359import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
359import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
360+import Streamly.Internal.Data.Time.Units
360−import Streamly.Internal.Data.Time.Units (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
361+ (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
361import Streamly.Internal.Data.Unfold.Types (Unfold(..))
362import Streamly.Internal.Data.Unfold.Types (Unfold(..))
362import Streamly.Internal.Data.Strict (Tuple3'(..))
363import Streamly.Internal.Data.Strict (Tuple3'(..))
@@ -3449,6 +3450,9 @@ pollCounts transf fld (Stream step state) = Stream step' Nothing
3450 {-# INLINE_LATE step' #-}
3451 {-# INLINE_LATE step' #-}
3451 step' _ Nothing = do
3452 step' _ Nothing = do
3453+ -- As long as we are using an "Int" for counts lockfree reads from
3454+ -- Var should work correctly on both 32-bit and 64-bit machines.
3455+ -- However, an Int on a 32-bit machine may overflow quickly.
3452 countVar <- liftIO $ newVar (0 :: Int)
3456 countVar <- liftIO $ newVar (0 :: Int)
3453 tid <- forkManaged
3457 tid <- forkManaged
3454 $ void $ runFold fld
3458 $ void $ runFold fld
@@ -4211,25 +4215,40 @@ dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
4211 Skip s -> Skip (DropByTimeYield s)
4215 Skip s -> Skip (DropByTimeYield s)
4212 Stop -> Stop
4216 Stop -> Stop
4218+-- XXX we should move this to stream generation section of this file. Also, the
4219+-- take/drop combinators above should be moved to filtering section.
4214{-# INLINE_NORMAL currentTime #-}
4220{-# INLINE_NORMAL currentTime #-}
4215currentTime :: MonadAsync m => Double -> Stream m AbsTime
4221currentTime :: MonadAsync m => Double -> Stream m AbsTime
4216currentTime g = Stream step Nothing
4222currentTime g = Stream step Nothing
4226+ g' = g * 10 ^ (6 :: Int)
4228+ -- XXX should have a minimum granularity to avoid high CPU usage?
4229+ {-# INLINE delayTime #-}
4231+ if g' >= fromIntegral (maxBound :: Int)
4218− next timeVar = do
4235+ updateTimeVar timeVar = do
4219 threadDelay $ delayTime
4236 threadDelay $ delayTime
4220 MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
4237 MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
4221 modifyVar' timeVar (const t)
4238 modifyVar' timeVar (const t)
4223− g' = g * 10 ^ (6 :: Int)
4224− {-# INLINE delayTime #-}
4225− delayTime = if g' >= fromIntegral (maxBound :: Int)
4228 {-# INLINE_LATE step #-}
4240 {-# INLINE_LATE step #-}
4229 step _ Nothing = do
4241 step _ Nothing = do
4242+ -- XXX note that this is safe only on a 64-bit machine. On a 32-bit
4243+ -- machine a 64-bit 'Var' cannot be read consistently without a lock
4244+ -- while another thread is writing to it.
4230 timeVar <- liftIO $ newVar (0 :: Int64)
4245 timeVar <- liftIO $ newVar (0 :: Int64)
4231− tid <- forkManaged $ liftIO $ void $ next timeVar
4246+ tid <- forkManaged $ liftIO $ forever (updateTimeVar timeVar)
4232 return $ Skip $ Just (timeVar, tid)
4247 return $ Skip $ Just (timeVar, tid)
4233 step _ s@(Just (timeVar, _)) = do
4249 step _ s@(Just (timeVar, _)) = do
4234 a <- liftIO $ readVar timeVar
4250 a <- liftIO $ readVar timeVar
4251+ -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
4252+ -- efficiency. or maybe we can use a representation using Double for
4253+ -- floating precision time
4235 return $ Yield (toAbsTime (MicroSecond64 a)) s
4254 return $ Yield (toAbsTime (MicroSecond64 a)) s