grapefruit-frp-0.0.0.0: src/Internal/CSeg.hs
{-# OPTIONS_GHC -fno-cse #-}
module Internal.CSeg (
CSeg,
currentValCapsule,
producer
) where
-- Control
import Control.Applicative as Applicative
import Control.Arrow as Arrow
import Control.Compose as Compose
import Control.Concurrent.MVar as MVar
-- Data
import Data.Unique as Unique
-- System
import System.IO.Unsafe as UnsafeIO
-- Internal
import Internal.Capsule as Capsule
import Internal.Circuit as Circuit
-- FRP.Grapefruit
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)
{-# NOINLINE unsafeCurrentValCapsule #-}
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