@@ -307,6 +307,10 @@ module Streamly.Internal.Data.Stream.StreamD
307307 , foldParallel
308308
309309 , lastN
310+
311+ -- * Time related
312+ , takeByTime
313+ , dropByTime
310314 )
311315where
312316
@@ -342,6 +346,8 @@ import qualified Prelude
342346
343347import Streamly.Internal.Mutable.Prim.Var
344348 (Prim, Var, readVar, newVar, modifyVar')
349+import Streamly.Internal.Data.Time.Units
350+
345351import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
346352import Streamly.Internal.Memory.Array.Types (Array(..))
347353import Streamly.Internal.Data.Fold.Types (Fold(..))
@@ -4034,3 +4040,56 @@ lastN n = Fold step initial done
40344040 foldFunc i
40354041 | i < n = RB.unsafeFoldRingM
40364042 | otherwise = RB.unsafeFoldRingFullM
4043+
4044+------------------------------------------------------------------------------
4045+-- Time related
4046+------------------------------------------------------------------------------
4047+
4048+-- XXX This does not fuse. Removing the if function results in fusion though.
4049+-- XXX This function will fuse with the use of fusion-plugin.
4050+-- XXX This function also fuses if compiled with -funfolding-use-threshold=500
4051+{-# INLINE_NORMAL takeByTime #-}
4052+takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4053+takeByTime lim' (Stream step state) = Stream step' (state, Nothing)
4054+ where
4055+ lim = toRelTime64 lim'
4056+ {-# INLINE_LATE step' #-}
4057+ step' _ (s, Nothing) = do
4058+ t <- liftIO $ getTime Monotonic
4059+ return $ Skip (s, Just t)
4060+ step' gst (s, jt@(Just t)) = do
4061+ ns <- step gst s
4062+ t' <- liftIO $ getTime Monotonic
4063+ if diffAbsTime64 t' t > lim
4064+ then return Stop
4065+ else return $ case ns of
4066+ Yield a s' -> Yield a (s', jt)
4067+ Skip s' -> Skip (s', jt)
4068+ Stop -> Stop
4069+
4070+-- XXX This does not fuse. Removing the if function results in fusion though.
4071+-- XXX This function will fuse with the use of fusion-plugin.
4072+-- XXX This function also fuses if compiled with -funfolding-use-threshold=500
4073+{-# INLINE_NORMAL dropByTime #-}
4074+dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4075+dropByTime lim' (Stream step state) = Stream step' (state, Nothing)
4076+ where
4077+ lim = toRelTime64 lim'
4078+ {-# INLINE_LATE step' #-}
4079+ step' _ (s, Nothing) = do
4080+ t <- liftIO $ getTime Monotonic
4081+ return $ Skip (s, Just t)
4082+ step' gst (s, jt@(Just t)) = do
4083+ t' <- liftIO $ getTime Monotonic
4084+ ns <- step gst s
4085+ if diffAbsTime64 t' t <= lim
4086+ then return $
4087+ case ns of
4088+ Yield _ s' -> Skip (s', jt)
4089+ Skip s' -> Skip (s', jt)
4090+ Stop -> Stop
4091+ else return $
4092+ case ns of
4093+ Yield a s' -> Yield a (s', jt)
4094+ Skip s' -> Skip (s', jt)
4095+ Stop -> Stop