module Simulation.Aivika.RealTime.Internal.Channel
(Channel,
newChannel,
channelEmpty,
readChannel,
writeChannel,
awaitChannel) where
import Data.List
import Data.IORef
import Control.Concurrent.STM
import Control.Monad
data Channel a =
Channel { forall a. Channel a -> TVar [a]
channelList :: TVar [a],
forall a. Channel a -> TVar Bool
channelListEmpty :: TVar Bool,
forall a. Channel a -> IORef Bool
channelListEmptyIO :: IORef Bool
}
newChannel :: IO (Channel a)
newChannel :: forall a. IO (Channel a)
newChannel =
do TVar [a]
list <- forall a. a -> IO (TVar a)
newTVarIO []
TVar Bool
listEmpty <- forall a. a -> IO (TVar a)
newTVarIO Bool
True
IORef Bool
listEmptyIO <- forall a. a -> IO (IORef a)
newIORef Bool
True
forall (m :: * -> *) a. Monad m => a -> m a
return Channel { channelList :: TVar [a]
channelList = TVar [a]
list,
channelListEmpty :: TVar Bool
channelListEmpty = TVar Bool
listEmpty,
channelListEmptyIO :: IORef Bool
channelListEmptyIO = IORef Bool
listEmptyIO }
channelEmpty :: Channel a -> IO Bool
channelEmpty :: forall a. Channel a -> IO Bool
channelEmpty Channel a
ch =
forall a. IORef a -> IO a
readIORef (forall a. Channel a -> IORef Bool
channelListEmptyIO Channel a
ch)
readChannel :: Channel a -> IO [a]
readChannel :: forall a. Channel a -> IO [a]
readChannel Channel a
ch =
do Bool
empty <- forall a. IORef a -> IO a
readIORef (forall a. Channel a -> IORef Bool
channelListEmptyIO Channel a
ch)
if Bool
empty
then forall (m :: * -> *) a. Monad m => a -> m a
return []
else do forall a. IORef a -> a -> IO ()
writeIORef (forall a. Channel a -> IORef Bool
channelListEmptyIO Channel a
ch) Bool
True
[a]
xs <- forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$
do [a]
xs <- forall a. TVar a -> STM a
readTVar (forall a. Channel a -> TVar [a]
channelList Channel a
ch)
forall a. TVar a -> a -> STM ()
writeTVar (forall a. Channel a -> TVar [a]
channelList Channel a
ch) []
forall a. TVar a -> a -> STM ()
writeTVar (forall a. Channel a -> TVar Bool
channelListEmpty Channel a
ch) Bool
True
forall (m :: * -> *) a. Monad m => a -> m a
return [a]
xs
forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. [a] -> [a]
reverse [a]
xs)
writeChannel :: Channel a -> a -> IO ()
writeChannel :: forall a. Channel a -> a -> IO ()
writeChannel Channel a
ch a
a =
do forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$
do [a]
xs <- forall a. TVar a -> STM a
readTVar (forall a. Channel a -> TVar [a]
channelList Channel a
ch)
forall a. TVar a -> a -> STM ()
writeTVar (forall a. Channel a -> TVar [a]
channelList Channel a
ch) (a
a forall a. a -> [a] -> [a]
: [a]
xs)
forall a. TVar a -> a -> STM ()
writeTVar (forall a. Channel a -> TVar Bool
channelListEmpty Channel a
ch) Bool
False
forall a. IORef a -> a -> IO ()
writeIORef (forall a. Channel a -> IORef Bool
channelListEmptyIO Channel a
ch) Bool
False
awaitChannel :: Channel a -> IO ()
awaitChannel :: forall a. Channel a -> IO ()
awaitChannel Channel a
ch =
forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$
do Bool
empty <- forall a. TVar a -> STM a
readTVar (forall a. Channel a -> TVar Bool
channelListEmpty Channel a
ch)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
empty forall a. STM a
retry