packages feed

hpc-tracer-0.3.0: src/Reactive.hs

module Reactive where

import Control.Concurrent
import Control.Exception as Exc
import Control.Concurrent.MVar

type Method s d = ((s -> IO s) -> IO ()) -> d
     
mkActor :: s -> Method s d -> IO d
mkActor initState body = do
   chan <- newChan

   let loop state = do body <- readChan chan
       	    	       state' <- body state
		       loop state'

   myForkIO $ loop initState

   return $ body (writeChan chan)

request :: (a -> s -> IO (r,s)) -> Method s (a -> IO r)
request fn send arg = do
   	     m  <- newEmptyMVar	
	     send (\ st -> do (rep,st') <- fn arg st
	     	  	      putMVar m rep
			      return st')
             takeMVar m 

mkActor3 :: s 
	 -> (     (forall r . (s -> IO (r,s)) -> IO r) 
	       -> (           (s -> IO s)     -> IO ()) 
	       -> actor)
	  -> IO actor
mkActor3 initState body = do
   state <- newMVar initState

   let reqs fn = do 
       s <- takeMVar state
       (r,s') <- fn s
       putMVar state s'
       return r

   let acts = undefined

   return $ body reqs acts

mkActor2 :: s 
	 -> (     (forall r . (s -> IO (r,s)) -> IO r) 
	       -> (           (s -> IO s)     -> IO ()) 
	       -> actor)
	  -> IO actor
mkActor2 initState body = do
   chan <- newChan

   let loop state = do body <- readChan chan
       	    	       state' <- body state
		       loop state'

   myForkIO $ loop initState

   let reqs fn = do
   	     m  <- newEmptyMVar	
	     writeChan chan $ \ st -> do (rep,st') <- fn st
	     	  	                 putMVar m rep
			                 return st'
             takeMVar m 

   let acts fn = do
       	    writeChan chan $ \ st -> fn st

   return $ body reqs acts

request2 :: ((s -> IO s) -> IO ()) -> (s -> IO (r,s)) -> IO r
request2 send fn = do
   	     m  <- newEmptyMVar	
	     send (\ st -> do (rep,st') <- fn st
	     	  	      putMVar m rep
			      return st')
             takeMVar m 

action :: (a -> s -> IO s) -> Method s (a -> IO ())
action fn send arg = send (fn arg)

test = mkActor ((99 :: Int))
           $ request (\ _a s -> return (show s,s + 1)) 

myForkIO m = do
	 forkIO (m `Exc.catch` \ e -> do
	 	   	       print "thread problem: "
	 	   	       print e
			       return ())

------------------------------------------------------------------------------

liftMethod :: ((a1 -> IO r1) -> (a2 -> IO r2) -> r)
	   -> Method s (a1 -> IO r1) 
	   -> Method s (a2 -> IO r2)
	   -> Method s r
liftMethod fn m1 m2 arg = fn (m1 arg) (m2 arg)

lift3Method :: ((a1 -> IO r1) -> (a2 -> IO r2) -> (a3 -> IO r3) -> r)
	   -> Method s (a1 -> IO r1) 
	   -> Method s (a2 -> IO r2)
	   -> Method s (a3 -> IO r3)
	   -> Method s r
lift3Method fn m1 m2 m3 arg = fn (m1 arg) (m2 arg) (m3 arg)