@@ -126,6 +126,7 @@ module Streamly.Internal.Data.Stream.StreamD
126 -- ** Specialized Folds
126 -- ** Specialized Folds
128 , tapAsync
128 , tapAsync
@@ -300,8 +301,9 @@ module Streamly.Internal.Data.Stream.StreamD
303−import Control.Concurrent (myThreadId, takeMVar)
304+import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
305+import Control.Exception
304−import Control.Exception (Exception, SomeException, fromException)
306+ (Exception, SomeException, AsyncException, fromException)
305import Control.Monad (void, when)
307import Control.Monad (void, when)
306import Control.Monad.Catch (MonadCatch, throwM)
308import Control.Monad.Catch (MonadCatch, throwM)
307import Control.Monad.IO.Class (MonadIO(..))
309import Control.Monad.IO.Class (MonadIO(..))
@@ -310,7 +312,7 @@ import Control.Monad.State.Strict (StateT)
310import Control.Monad.Trans (MonadTrans(lift))
312import Control.Monad.Trans (MonadTrans(lift))
311import Data.Bits (shiftR, shiftL, (.|.), (.&.))
313import Data.Bits (shiftR, shiftL, (.|.), (.&.))
312import Data.Functor.Identity (Identity(..))
314import Data.Functor.Identity (Identity(..))
313−import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
315+import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, modifyIORef')
314import Data.Maybe (fromJust, isJust, isNothing)
316import Data.Maybe (fromJust, isJust, isNothing)
315import Data.Word (Word32)
317import Data.Word (Word32)
316import Foreign.Ptr (Ptr)
318import Foreign.Ptr (Ptr)
@@ -3218,6 +3220,51 @@ tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
3218 void $ extract acc
3220 void $ extract acc
3219 return $ Stop
3221 return $ Stop
3223+{-# INLINE_NORMAL tapRate #-}
3225+ (MonadAsync m, MonadCatch m)
3230+tapRate samplingRate action (Stream step state) = Stream step' Nothing
3232+ {-# NOINLINE loop #-}
3233+ loop countRef prev = do
3236+ (do liftIO $ threadDelay (round $ samplingRate * 1000000)
3237+ i <- liftIO $ readIORef countRef
3238+ let !diff = i - prev
3241+ (\(e :: AsyncException) -> do
3242+ i <- liftIO $ readIORef countRef
3243+ let !diff = i - prev
3245+ throwM (MC.toException e))
3248+ {-# INLINE_LATE step' #-}
3249+ step' _ Nothing = do
3250+ countRef <- liftIO $ newIORef 0
3251+ tid <- fork $ loop countRef 0
3252+ ref <- liftIO $ newIORef ()
3253+ _ <- liftIO $ mkWeakIORef ref (killThread tid)
3254+ return $ Skip (Just (countRef, tid, state, ref))
3256+ step' gst (Just (countRef, tid, st, ref)) = do
3260+ liftIO $ modifyIORef' countRef (+ 1)
3261+ return $ Yield x (Just (countRef, tid, s, ref))
3262+ Skip s -> return $ Skip (Just (countRef, tid, s, ref))
3264+ liftIO $ killThread tid
3221-------------------------------------------------------------------------------
3268-------------------------------------------------------------------------------
3222-- Filtering
3269-- Filtering
3223-------------------------------------------------------------------------------
3270-------------------------------------------------------------------------------