2-- Module : Streamly.Internal.Data.Unfold.SVar
3-- Copyright : (c) 2019 Composewell Technologies
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
9module Streamly.Internal.Data.Unfold.SVar
18import Control.Exception (fromException)
19import Control.Monad (when)
20import Control.Monad.IO.Class (MonadIO(..))
21import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
22import Data.Maybe (isNothing)
23import Streamly.Internal.Control.Concurrent (MonadAsync)
24import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
25import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
26import Streamly.Internal.Data.SVar (printSVar, cleanupSVar, sendStopToProducer)
27import System.Mem (performMajorGC)
29import qualified Control.Monad.Catch as MC
31import Streamly.Internal.Data.SVar.Type
32import Streamly.Internal.Data.Unfold.Type
34 hiding (map, mapM, takeWhile, take, filter, const, zipWith
35 , drop, dropWhile, either)
37-------------------------------------------------------------------------------
38-- Generation from SVar
39-------------------------------------------------------------------------------
41data FromSVarState t m a =
42 FromSVarInit (SVar t m a)
43 | FromSVarRead (SVar t m a)
44 | FromSVarLoop (SVar t m a) [ChildEvent a]
45 | FromSVarDone (SVar t m a)
49{-# INLINE_NORMAL fromSVar #-}
50fromSVar :: MonadAsync m => Unfold m (SVar t m a) a
51fromSVar = Unfold step (return . FromSVarInit)
54 {-# INLINE_LATE step #-}
55 step (FromSVarInit svar) = do
56 ref <- liftIO $ newIORef ()
57 _ <- liftIO $ mkWeakIORef ref hook
58 -- when this copy of svar gets garbage collected "ref" will get
59 -- garbage collected and our GC hook will be called.
60 let sv = svar{svarRef = Just ref}
61 return $ Skip (FromSVarRead sv)
67 when (svarInspectMode svar) $ do
68 r <- liftIO $ readIORef (svarStopTime (svarStats svar))
70 printSVar svar "SVar Garbage Collected"
72 -- If there are any SVars referenced by this SVar a GC will prompt
73 -- them to be cleaned up quickly.
74 when (svarInspectMode svar) performMajorGC
76 step (FromSVarRead sv) = do
77 list <- readOutputQ sv
78 -- Reversing the output is important to guarantee that we process the
79 -- outputs in the same order as they were generated by the constituent
81 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
83 step (FromSVarLoop sv []) = do
84 done <- postProcess sv
85 return $ Skip $ if done
89 step (FromSVarLoop sv (ev : es)) = do
91 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
96 stop <- shouldStop tid
99 liftIO (cleanupSVar sv)
100 return $ Skip (FromSVarDone sv)
101 else return $ Skip (FromSVarLoop sv es)
103 case fromException ex of
105 return $ Skip (FromSVarLoop sv es)
106 Nothing -> liftIO (cleanupSVar sv) >> MC.throwM ex
110 case svarStopStyle sv of
111 StopNone -> return False
112 StopAny -> return True
114 sid <- liftIO $ readIORef (svarStopBy sv)
117 step (FromSVarDone sv) = do
118 when (svarInspectMode sv) $ do
119 t <- liftIO $ getTime Monotonic
120 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
121 liftIO $ printSVar sv "SVar Done"
124-------------------------------------------------------------------------------
125-- Process events received by a fold consumer from a stream producer
126-------------------------------------------------------------------------------
128-- XXX Have an error for "FromSVarInit" instead of undefined. The error can
129-- redirect the user to report the failure to the developers.
132{-# INLINE_NORMAL fromProducer #-}
133fromProducer :: MonadAsync m => Unfold m (SVar t m a) a
134fromProducer = Unfold step (return . FromSVarRead)
137 {-# INLINE_LATE step #-}
138 step (FromSVarRead sv) = do
139 list <- readOutputQ sv
140 -- Reversing the output is important to guarantee that we process the
141 -- outputs in the same order as they were generated by the constituent
143 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
145 step (FromSVarLoop sv []) = return $ Skip $ FromSVarRead sv
146 step (FromSVarLoop sv (ev : es)) = do
148 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
149 ChildStop tid e -> do
153 sendStopToProducer sv
154 return $ Skip (FromSVarDone sv)
155 Just _ -> error "Bug: fromProducer: received exception"
157 step (FromSVarDone sv) = do
158 when (svarInspectMode sv) $ do
159 t <- liftIO $ getTime Monotonic
160 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
161 liftIO $ printSVar sv "SVar Done"
164 step (FromSVarInit _) = undefined
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list