module Server.ResponseController
( ResponseController
, new
, dispatch
, setCheckpointAndWait
) where
import Control.Concurrent
import Control.Concurrent.SizedChan
import Control.Monad ( void
, when
)
import Data.IORef
data ResponseController = ResponseController
{
ResponseController -> IORef Int
dispatchedCount :: IORef Int
,
ResponseController -> IORef Int
completedCount :: IORef Int
,
ResponseController -> SizedChan Checkpoint
checkpointChan :: SizedChan Checkpoint
}
type Checkpoint = (Int, () -> IO ())
new :: IO ResponseController
new :: IO ResponseController
new = IORef Int
-> IORef Int -> SizedChan Checkpoint -> ResponseController
ResponseController forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> IO (IORef a)
newIORef Int
0 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. a -> IO (IORef a)
newIORef Int
0 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. IO (SizedChan a)
newSizedChan
dispatch :: ResponseController -> IO (() -> IO ())
dispatch :: ResponseController -> IO (() -> IO ())
dispatch ResponseController
controller = do
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' (ResponseController -> IORef Int
dispatchedCount ResponseController
controller) forall a. Enum a => a -> a
succ
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ \() -> do
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' (ResponseController -> IORef Int
completedCount ResponseController
controller) forall a. Enum a => a -> a
succ
Maybe Checkpoint
result <- forall a. SizedChan a -> IO (Maybe a)
tryPeekSizedChan (ResponseController -> SizedChan Checkpoint
checkpointChan ResponseController
controller)
case Maybe Checkpoint
result of
Maybe Checkpoint
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just (Int
dispatched, () -> IO ()
callback) -> do
Int
completed <- forall a. IORef a -> IO a
readIORef (ResponseController -> IORef Int
completedCount ResponseController
controller)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
dispatched forall a. Eq a => a -> a -> Bool
== Int
completed) forall a b. (a -> b) -> a -> b
$ do
() -> IO ()
callback ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall a. SizedChan a -> IO a
readSizedChan (ResponseController -> SizedChan Checkpoint
checkpointChan ResponseController
controller)
setCheckpoint :: ResponseController -> (() -> IO ()) -> IO ()
setCheckpoint :: ResponseController -> (() -> IO ()) -> IO ()
setCheckpoint ResponseController
controller () -> IO ()
callback = do
Int
dispatched <- forall a. IORef a -> IO a
readIORef (ResponseController -> IORef Int
dispatchedCount ResponseController
controller)
Int
completed <- forall a. IORef a -> IO a
readIORef (ResponseController -> IORef Int
completedCount ResponseController
controller)
if Int
dispatched forall a. Eq a => a -> a -> Bool
== Int
completed
then () -> IO ()
callback ()
else do
let checkpoint :: Checkpoint
checkpoint = (Int
dispatched, () -> IO ()
callback)
forall a. SizedChan a -> a -> IO ()
writeSizedChan (ResponseController -> SizedChan Checkpoint
checkpointChan ResponseController
controller) Checkpoint
checkpoint
setCheckpointAndWait :: ResponseController -> IO ()
setCheckpointAndWait :: ResponseController -> IO ()
setCheckpointAndWait ResponseController
controller = do
MVar ()
mvar <- forall a. IO (MVar a)
newEmptyMVar
ResponseController -> (() -> IO ()) -> IO ()
setCheckpoint ResponseController
controller (forall a. MVar a -> a -> IO ()
putMVar MVar ()
mvar)
forall a. MVar a -> IO a
takeMVar MVar ()
mvar