packages feed

transient 0.1.0.0 → 0.1.0.1

raw patch · 3 files changed

+79/−11 lines, 3 files

Files

Main.hs view
@@ -34,7 +34,7 @@ 
       nonDeterminsm <|> trans <|>
              colors <|> app   <|>
-            futures <|> server <|> 
+            futures <|> server <|>
             distributed <|> pubSub
 
 solveConstraint=  do
@@ -320,24 +320,24 @@ pubSub=  do
   option "pubs" "an example of publish-subscribe using Event Vars (EVars)"
   v <- newEVar  :: TransIO (EVar String)
-  v' <- newEVar 
+  v' <- newEVar
   suscribe v v' <|> publish v v'
-  where 
-      
+  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
     liftIO $ putStrLn "after writing second EVar\n"
     publish v v'
-    
+
   suscribe :: EVar String -> EVar String -> TransIO ()
   suscribe v v'= do
        r <- (,) <$> proc1 v  <*>  proc2 v'
        liftIO $ do
-             putStr $ "applicative result= " 
+             putStr "applicative result= "
              print r
 
   suscribe2 ::  EVar String -> EVar String -> TransIO ()
@@ -349,10 +349,10 @@                  print (x,y)
 
   proc1 v=  do
-    msg <- readEVar v 
+    msg <- readEVar v
     liftIO $ putStrLn $  "proc1 readed var: " ++ show msg
     return msg
-    
+
   proc2 v= do
     msg <- readEVar v
     liftIO $ putStrLn $ "proc2 readed var: " ++ show msg
+ src/Transient/EVars.hs view
@@ -0,0 +1,68 @@+{-# 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.0
+version: 0.1.0.1
 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
+    exposed-modules: Transient.Indeterminism Transient.Base Transient.EVars
                      Transient.Backtrack Transient.Move Transient.Logged
     exposed: True
     buildable: True