on master help sign in
Remove Coroutine and simplify Env operations
commit6a84a0f005a474600e0f7c322d1b3553b84207f3 authorAndrzej Rybczak <andrzej@rybczak.net> dateMon 14 Jun 2021, 22:50 (5 years ago) parent7d6088d
6 files changed+24−153
effectful.cabal−1 src/Effectful/Coroutine.hs−89 src/Effectful/Error.hs+3−3 src/Effectful/Internal/Env.hs+13−52 src/Effectful/Internal/Monad.hs+6−6 src/Effectful/Resource.hs+2−2
effectful.cabal−1
@@ -71,7 +71,6 @@ library
7171 Effectful.Class.Reader
7272 Effectful.Class.State
7373 Effectful.Class.Writer
74− Effectful.Coroutine
7574 Effectful.Error
7675 Effectful.Internal.Env
7776 Effectful.Internal.Has
src/Effectful/Coroutine.hsdeleted−89
@@ -1,89 +0,0 @@
1−-- | Experimental support for coroutines.
2−module Effectful.Coroutine
3− ( Coroutine
4− , Status(..)
5− , runCoroutine
6− , yield
7− ) where
8−
9−import Control.Concurrent.MVar
10−import Control.Exception
11−import Data.Function
12−import qualified Control.Concurrent as C
13−
14−import Effectful.Internal.Env
15−import Effectful.Internal.Has
16−import Effectful.Internal.Monad
17−
18−data Coroutine o i = forall es r. Coroutine
19− { crInput :: MVar (i, Env es)
20− , crState :: MVar (State o r)
21− , crCallerEnvSize :: Int
22− }
23−
24−data Status es o i r
25− = Done r
26− | Yielded o (i -> Eff es (Status es o i r))
27−
28−runCoroutine :: Eff (Coroutine o i : es) r -> Eff es (Status es o i r)
29−runCoroutine (Eff m) = impureEff $ \es -> do
30− size <- sizeEnv es
31− mvInput <- newEmptyMVar
32− mvState <- newEmptyMVar
33− mask $ \restore -> do
34− -- Create a worker thread and continue execution there.
35− tid <- C.forkIO $ do
36− let cr = Coroutine mvInput mvState size
37− er <- try $ restore . m =<< unsafeConsEnv cr es
38− tryPutMVar mvState (either Failure Success er) >>= \case
39− False -> error "unexpected"
40− True -> pure ()
41− waitForStatus restore es size tid mvInput mvState
42−
43−yield :: Coroutine o i :> es => o -> Eff es i
44−yield o = impureEff $ \es -> mask $ \restore -> do
45− Coroutine{..} <- getEnv es
46− size <- sizeEnv es
47− -- Save local part of the environment as the caller will discard it.
48− localEs <- takeLastEnv (size - crCallerEnvSize) es
49− -- Pass control to the caller.
50− tryPutMVar crState (Yield o) >>= \case
51− False -> error "unexpected"
52− True -> do
53− (i, callerEs) <- restore $ takeMVar crInput
54− -- The caller resumed, reconstruct the local environment. The environment
55− -- needs to be replaced since the one we just got might be completely
56− -- different to what we had before suspending the computation, e.g. if the
57− -- computation was resumed in a different thread.
58− unsafeReplaceEnv es =<< unsafeAppendEnv callerEs localEs
59− pure i
60−
61−----------------------------------------
62−-- Internal
63−
64−data State o r where
65− Failure :: SomeException -> State o r
66− Success :: r -> State o r
67− Yield :: o -> State o r
68−
69−waitForStatus
70− :: (forall a. IO a -> IO a)
71− -> Env es
72− -> Int
73− -> C.ThreadId
74− -> MVar (i, Env es)
75− -> MVar (State o r)
76− -> IO (Status es o i r)
77−waitForStatus restore0 es0 size0 tid mvInput mvState = fix $ \loop -> do
78− try @SomeException (restore0 $ takeMVar mvState) >>= \case
79− Left e -> throwTo tid e >> loop
80− Right (Failure e) -> throwIO e
81− Right (Success r) -> Done r <$ unsafeTrimEnv size0 es0
82− Right (Yield o) -> Yielded o k <$ unsafeTrimEnv size0 es0
83− where
84− k i = impureEff $ \es -> mask $ \restore -> do
85− size <- sizeEnv es
86− -- Resume suspended computation with the current environment.
87− tryPutMVar mvInput (i, es) >>= \case
88− False -> error "unexpected"
89− True -> waitForStatus restore es size tid mvInput mvState
src/Effectful/Error.hs+3−3
@@ -24,11 +24,11 @@ runError
2424 => Eff (Error e : es) a
2525 -> Eff es (Either ([String], e) a)
2626runError (Eff m) = impureEff $ \es0 -> mask $ \release -> do
27− size <- sizeEnv es0
27+ size0 <- sizeEnv es0
2828 es <- unsafeConsEnv (Error @e) es0
2929 try (release $ m es) >>= \case
30− Right a -> Right a <$ unsafeTrimEnv size es
31− Left (WrapE cs e) -> Left (cs, e) <$ unsafeTrimEnv size es
30+ Right a -> Right a <$ unsafeTailEnv size0 es
31+ Left (WrapE cs e) -> Left (cs, e) <$ unsafeTailEnv size0 es
3232
3333throwError
3434 :: (HasCallStack, Exception e, Error e :> es)
src/Effectful/Internal/Env.hs+13−52
@@ -10,15 +10,12 @@ module Effectful.Internal.Env
1010 , emptyEnv
1111 , cloneEnv
1212 , sizeEnv
13− , takeLastEnv
1413 , getEnv
1514 , checkSizeEnv
1615
1716 -- * Extending and shrinking
18− , unsafeReplaceEnv
1917 , unsafeConsEnv
20− , unsafeAppendEnv
21− , unsafeTrimEnv
18+ , unsafeTailEnv
2219
2320 -- * Data retrieval and update
2421 , unsafePutEnv
@@ -61,14 +58,6 @@ sizeEnv (Env ref) = do
6158 EnvRef n _ <- readIORef ref
6259 pure n
6360
64−-- | Take last @k@ values from the top of the environment.
65−takeLastEnv :: HasCallStack => Int -> Env es0 -> IO (Env es)
66−takeLastEnv k (Env ref) = do
67− EnvRef n es <- readIORef ref
68− if k > n
69− then error $ "k (" ++ show k ++ ") > n (" ++ show n ++ ")"
70− else fmap Env . newIORef . EnvRef k =<< cloneSmallMutableArray es (n - k) k
71−
7261-- | Extract a specific data type from the environment.
7362getEnv :: forall e es. (HasCallStack, e :> es) => Env es -> IO e
7463getEnv (Env ref) = do
@@ -84,11 +73,7 @@ checkSizeEnv k (Env ref) = do
8473----------------------------------------
8574-- Extending and shrinking
8675
87−-- | Replace the first argument with the second one in place.
88−unsafeReplaceEnv :: HasCallStack => Env es -> Env es -> IO ()
89−unsafeReplaceEnv (Env ref0) (Env ref1) = writeIORef ref0 =<< readIORef ref1
90−
91−-- | Extend the environment with a new data type in place.
76+-- | Extend the environment with a new data type (in place).
9277unsafeConsEnv :: HasCallStack => e -> Env es -> IO (Env (e : es))
9378unsafeConsEnv e (Env ref) = do
9479 EnvRef n es0 <- readIORef ref
@@ -107,47 +92,23 @@ unsafeConsEnv e (Env ref) = do
10792 pure $ Env ref
10893{-# NOINLINE unsafeConsEnv #-}
10994
110−-- | Extend the first environment with the second one in place.
111−unsafeAppendEnv :: HasCallStack => Env es0 -> Env es1 -> IO (Env es)
112−unsafeAppendEnv (Env ref0) (Env ref1) = do
113− EnvRef n0 es0 <- readIORef ref0
114− EnvRef n1 es1 <- readIORef ref1
115− let n = n0 + n1
116− if n <= sizeofSmallMutableArray es0
117− then do
118− copySmallMutableArray es0 n0 es1 0 n1
119− writeIORef ref0 $! EnvRef n es0
120− pure $ Env ref0
121− else do
122− es <- newSmallArray n (error "undefined field")
123− copySmallMutableArray es 0 es0 0 n0
124− copySmallMutableArray es n0 es1 0 n1
125− writeIORef ref0 $! EnvRef n es
126− pure $ Env ref0
127−{-# NOINLINE unsafeAppendEnv #-}
128−
129−-- | Trim the environment to the given size in place.
130−unsafeTrimEnv :: HasCallStack => Int -> Env es -> IO (Env es0)
131−unsafeTrimEnv k (Env ref) = do
95+-- | Shrink the environment by one data type (in place). Makes sure the size of
96+-- the environment is as expected.
97+unsafeTailEnv :: HasCallStack => Int -> Env (e : es) -> IO (Env es)
98+unsafeTailEnv k (Env ref) = do
13299 EnvRef n es <- readIORef ref
133− if k > n
134− then error $ "k (" ++ show k ++ ") > n (" ++ show n ++ ")"
100+ if k /= n - 1
101+ then error $ "k (" ++ show k ++ ") /= n - 1 (" ++ show (n - 1) ++ ")"
135102 else do
136− overwrite es k (n - k)
103+ writeSmallArray es k (error "undefined field")
137104 writeIORef ref $! EnvRef k es
138105 pure $ Env ref
139− where
140− overwrite es base = \case
141− 0 -> pure ()
142− i -> do
143− writeSmallArray es (base + i - 1) (error "undefined field")
144− overwrite es base (i - 1)
145−{-# NOINLINE unsafeTrimEnv #-}
106+{-# NOINLINE unsafeTailEnv #-}
146107
147108----------------------------------------
148109-- Data retrieval and update
149110
150−-- | Replace the data type in the environment with a new value in place.
111+-- | Replace the data type in the environment with a new value (in place).
151112unsafePutEnv
152113 :: forall e es. (HasCallStack, e :> es)
153114 => e
@@ -157,7 +118,7 @@ unsafePutEnv e (Env ref) = do
157118 EnvRef n es <- readIORef ref
158119 e `seq` writeSmallArray es (ixEnv @e @es n) (toAny e)
159120
160−-- | Modify the data type in the environment in place.
121+-- | Modify the data type in the environment (in place).
161122unsafeModifyEnv
162123 :: forall e es. (HasCallStack, e :> es)
163124 => (e -> e)
@@ -169,7 +130,7 @@ unsafeModifyEnv f (Env ref) = do
169130 e <- f . fromAny <$> readSmallArray es i
170131 e `seq` writeSmallArray es i (toAny e)
171132
172−-- | Modify the data type in the enviroment in place and return a value.
133+-- | Modify the data type in the enviroment (in place) and return a value.
173134unsafeStateEnv
174135 :: forall e es a. (HasCallStack, e :> es)
175136 => (e -> (a, e))
src/Effectful/Internal/Monad.hs+6−6
@@ -138,23 +138,23 @@ runInIO f = impureEff $ \es -> do
138138
139139runEffect :: e -> Eff (e : es) a -> Eff es (a, e)
140140runEffect e0 (Eff m) = impureEff $ \es0 -> do
141− size <- sizeEnv es0
141+ size0 <- sizeEnv es0
142142 bracket (unsafeConsEnv e0 es0)
143− (unsafeTrimEnv size)
143+ (unsafeTailEnv size0)
144144 (\es -> (,) <$> m es <*> getEnv es)
145145
146146evalEffect :: e -> Eff (e : es) a -> Eff es a
147147evalEffect e (Eff m) = impureEff $ \es0 -> do
148− size <- sizeEnv es0
148+ size0 <- sizeEnv es0
149149 bracket (unsafeConsEnv e es0)
150− (unsafeTrimEnv size)
150+ (unsafeTailEnv size0)
151151 (\es -> m es)
152152
153153execEffect :: e -> Eff (e : es) a -> Eff es e
154154execEffect e0 (Eff m) = impureEff $ \es0 -> do
155− size <- sizeEnv es0
155+ size0 <- sizeEnv es0
156156 bracket (unsafeConsEnv e0 es0)
157− (unsafeTrimEnv size)
157+ (unsafeTailEnv size0)
158158 (\es -> m es *> getEnv es)
159159
160160getEffect :: e :> es => Eff es e
src/Effectful/Resource.hs+2−2
@@ -32,10 +32,10 @@ runResource (Eff m) = impureEff $ \es0 -> do
3232 mask $ \restore -> do
3333 es <- unsafeConsEnv (Resource istate) es0
3434 a <- restore (m es) `catch` \e -> do
35− _ <- unsafeTrimEnv size0 es
35+ _ <- unsafeTailEnv size0 es
3636 RI.stateCleanupChecked (Just e) istate
3737 throwIO e
38− _ <- unsafeTrimEnv size0 es
38+ _ <- unsafeTailEnv size0 es
3939 RI.stateCleanupChecked Nothing istate
4040 pure a
4141