transient 0.1.0.2 → 0.1.0.3
raw patch · 4 files changed
+16/−79 lines, 4 filesdep ~base
Dependency ranges changed: base
Files
- Main.hs +5/−4
- src/Transient/Base.hs +9/−5
- src/Transient/EVars.hs +0/−68
- transient.cabal +2/−2
Main.hs view
@@ -320,14 +320,15 @@ pubSub= do option "pubs" "an example of publish-subscribe using Event Vars (EVars)" v <- newEVar :: TransIO (EVar String) - v' <- newEVar + + v' <- newEVar subscribe v v' <|> publish v v' - liftIO $ putStrLn ".............." where - + publish v v'= do liftIO $ putStrLn "Enter a message to publish" - msg <- input(const True) + msg <- input(const True) + writeEVar v msg liftIO $ putStrLn "after writing first EVar\n" writeEVar v' $ "second " ++ msg
src/Transient/Base.hs view
@@ -62,12 +62,13 @@ } deriving Typeable + type P= IORef newp= newIORef --(=:) :: P a -> (a -> a) -> IO() -(=:) n f= liftIO $ atomicModifyIORef' n $ \v -> ((f v),()) +(=:) n f= liftIO $ atomicModifyIORef n $ \v -> ((f v),()) addr x= show $ unsafePerformIO $ do st <- makeStableName $! x @@ -282,8 +283,8 @@ -- * Threads -waitQSemB sem= atomicModifyIORef' sem $ \n -> if n > 0 then(n-1,True) else (n,False) -signalQSemB sem= atomicModifyIORef' sem $ \n -> (n + 1,()) +waitQSemB sem= atomicModifyIORef sem $ \n -> if n > 0 then(n-1,True) else (n,False) +signalQSemB sem= atomicModifyIORef sem $ \n -> (n + 1,()) -- | set the maximun number of threads for a procedure. It is useful for the threads :: Int -> TransientIO a -> TransientIO a @@ -475,7 +476,7 @@ if dofork then do - th <- forkFinally proc $ \me -> do + th <- forkFinally1 proc $ \me -> do case me of -- !> "THREAD ENDED" of Left e -> do when (fromException e /= Just ThreadKilled)$ liftIO $ print e @@ -505,7 +506,10 @@ else proc -- !> "NO THREAD" - +forkFinally1 :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId +forkFinally1 action and_then = + mask $ \restore -> + forkIO $ try (restore action) >>= and_then free th env= do if isNothing $ parent env
− src/Transient/EVars.hs
@@ -1,68 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-} -module Transient.EVars where - -import Transient.Base -import qualified Data.Map as M -import Data.Typeable - -import Control.Concurrent -import Control.Applicative -import Data.IORef -import Control.Monad.IO.Class -import Control.Monad.State - -newtype EVars= EVars (IORef (M.Map Int [EventF])) deriving Typeable - -data EVar a= EVar Int (IORef (Maybe a)) - --- * Evars are event vars. `writeEVar` trigger the execution of all the continuations associated to the `readEVar` of this variable --- (the code that is after them) as stack: the most recent reads are executed first. --- --- It is like the publish-subscribe pattern but without inversion of control, since a readEVar can be inserted at any place in the --- Transient flow. --- --- EVars are created upstream and can be used to communicate two sub-threads of the monad. Following the Transient philosophy they --- do not block his own thread if used with alternative operators, unlike the IORefs and TVars. And unlike STM vars, that are composable, --- they wait for their respective events, while TVars execute the whole expression when any variable is modified. --- --- The execution continues after the writeEVar when all subscribers have been executed. --- --- see https://www.fpcomplete.com/user/agocorona/publish-subscribe-variables-transient-effects-v --- - - -newEVar :: TransientIO (EVar a) -newEVar = Transient $ do - EVars ref <- getSessionData `onNothing` do - ref <- liftIO $ newIORef M.empty - setSData $ EVars ref - return (EVars ref) - id <- genNewId - ref <- liftIO $ newIORef Nothing - return . Just $ EVar id ref - -readEVar :: EVar a -> TransIO a -readEVar (EVar id ref1)= Transient $ do - mr <- liftIO $ readIORef ref1 - case mr of - Just _ -> return mr - Nothing -> do - cont <- getCont - EVars ref <- getSessionData `onNothing` error "No Events context" - map <- liftIO $ readIORef ref - let Just conts= M.lookup id map <|> Just [] - liftIO $ writeIORef ref $ M.insert id (cont:conts) map - return Nothing - -writeEVar (EVar id ref1) x= Transient $ do - EVars ref <- getSessionData `onNothing` error "No Events context" - liftIO $ writeIORef ref1 $ Just x - map <- liftIO $ readIORef ref - let Just conts= M.lookup id map <|> Just [] - mapM runCont conts - liftIO $ writeIORef ref1 Nothing - return $ Just () - - - -
transient.cabal view
@@ -2,7 +2,7 @@ synopsis: A monad for extensible effects and primitives for unrestricted composability of applications homepage: http://www.fpcomplete.com/user/agocorona bug-reports: https://github.com/agocorona/transient/issues -version: 0.1.0.2 +version: 0.1.0.3 cabal-version: >=1.10 build-type: Simple license: GPL-3 @@ -20,7 +20,7 @@ directory -any, filepath -any, stm -any, HTTP -any, network -any, transformers -any, process -any, network-info -any - exposed-modules: Transient.Indeterminism Transient.Base Transient.EVars + exposed-modules: Transient.Indeterminism Transient.Base Transient.Backtrack Transient.Move Transient.Logged exposed: True buildable: True