module Internal.CSeg (
CSeg,
currentValCapsule,
producer
) where
import Control.Applicative as Applicative
import Control.Arrow as Arrow
import Control.Compose as Compose
import Control.Concurrent.MVar as MVar
import Data.Unique as Unique
import System.IO.Unsafe as UnsafeIO
import Internal.Capsule as Capsule
import Internal.Circuit as Circuit
import FRP.Grapefruit.Circuit as Circuit
newtype CSeg val = CSeg (((->) Unique :. Capsule) val) deriving (Functor, Applicative)
currentValCapsule :: Unique -> CSeg val -> Capsule val
currentValCapsule currentTimeID (CSeg capsuleGen) = unO capsuleGen currentTimeID
producer :: IO val -> Circuit era () (CSeg val)
producer readVal = proc _ -> do
maybeValVar <- act -< newMVar Nothing
addECFinalizer <- getECFinalizerAdd -< ()
returnA -< CSeg $
O (unsafeCurrentValCapsule readVal maybeValVar addECFinalizer)
unsafeCurrentValCapsule :: IO val
-> MVar (Maybe val)
-> (IO () -> IO ())
-> Unique
-> Capsule val
unsafeCurrentValCapsule readVal maybeValVar addECFinalizer timeID = unsafePerformIO $
seq timeID $
getCurrentValCapsule where
getCurrentValCapsule = do
maybeVal <- readMVar maybeValVar
case maybeVal of
Nothing -> do
val <- readVal
putMVar maybeValVar (Just val)
addECFinalizer resetMaybeValVar
return (Applicative.pure val)
justVal@(Just val) -> do
putMVar maybeValVar justVal
return (Applicative.pure val)
resetMaybeValVar = do
readMVar maybeValVar
putMVar maybeValVar Nothing