2{-# LANGUAGE FlexibleContexts #-}
5-- Module : Streamly.Streams.SVar
6-- Copyright : (c) 2017 Harendra Kumar
9-- Maintainer : streamly@composewell.com
10-- Stability : experimental
14module Streamly.Streams.SVar
21import Control.Exception (fromException)
22import Control.Monad (when)
23import Control.Monad.Catch (throwM)
24import Control.Monad.IO.Class (MonadIO(liftIO))
25import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
26import Data.Maybe (isNothing)
27#if __GLASGOW_HASKELL__ < 808
28import Data.Semigroup ((<>))
30import System.IO (hPutStrLn, stderr)
31import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
32import System.Mem (performMajorGC)
34import Streamly.Internal.Data.SVar
35import Streamly.Streams.StreamK hiding (reverse)
37printSVar :: SVar t m a -> String -> IO ()
40 hPutStrLn stderr $ "\n" <> how <> "\n" <> svInfo
42-- | Pull a stream from an SVar.
43{-# NOINLINE fromStreamVar #-}
44fromStreamVar :: MonadAsync m => SVar Stream m a -> Stream m a
45fromStreamVar sv = mkStream $ \st yld sng stp -> do
46 list <- readOutputQ sv
47 -- Reversing the output is important to guarantee that we process the
48 -- outputs in the same order as they were generated by the constituent
50 foldStream st yld sng stp $ processEvents $ reverse list
55 when (svarInspectMode sv) $ do
56 t <- liftIO $ getTime Monotonic
57 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
58 liftIO $ printSVar sv "SVar Done"
61 {-# INLINE processEvents #-}
62 processEvents [] = mkStream $ \st yld sng stp -> do
63 done <- postProcess sv
66 else foldStream st yld sng stp $ fromStreamVar sv
68 processEvents (ev : es) = mkStream $ \st yld sng stp -> do
69 let rest = processEvents es
71 ChildYield a -> yld a rest
76 stop <- shouldStop tid
78 then liftIO (cleanupSVar sv) >> allDone stp
79 else foldStream st yld sng stp rest
81 case fromException ex of
83 foldStream st yld sng stp rest
84 Nothing -> liftIO (cleanupSVar sv) >> throwM ex
86 case svarStopStyle sv of
87 StopNone -> return False
88 StopAny -> return True
90 sid <- liftIO $ readIORef (svarStopBy sv)
91 return $ if tid == sid then True else False
93{-# INLINE fromSVar #-}
94fromSVar :: (MonadAsync m, IsStream t) => SVar Stream m a -> t m a
96 mkStream $ \st yld sng stp -> do
97 ref <- liftIO $ newIORef ()
98 _ <- liftIO $ mkWeakIORef ref hook
99 -- We pass a copy of sv to fromStreamVar, so that we know that it has
100 -- no other references, when that copy gets garbage collected "ref"
101 -- will get garbage collected and our hook will be called.
102 foldStreamShared st yld sng stp $
103 fromStream $ fromStreamVar sv{svarRef = Just ref}
107 when (svarInspectMode sv) $ do
108 r <- liftIO $ readIORef (svarStopTime (svarStats sv))
110 printSVar sv "SVar Garbage Collected"
112 -- If there are any SVars referenced by this SVar a GC will prompt
113 -- them to be cleaned up quickly.
114 when (svarInspectMode sv) performMajorGC
116-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
117-- be read back from the SVar using 'fromSVar'.
118toSVar :: (IsStream t, MonadAsync m) => SVar Stream m a -> t m a -> m ()
119toSVar sv m = toStreamVar sv (toStream m)
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