{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
module Network.TypedProtocol.Driver
(
Driver (..)
, SomeMessage (..)
, runPeerWithDriver
, runPipelinedPeerWithDriver
) where
import Data.Void (Void)
import Network.TypedProtocol.Core
import Network.TypedProtocol.Pipelined
import Control.Monad.Class.MonadAsync
import Control.Monad.Class.MonadFork
import Control.Monad.Class.MonadSTM
data Driver ps dstate m =
Driver {
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage :: forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st
-> Message ps st st'
-> m ()
, Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st
-> dstate
-> m (SomeMessage st, dstate)
, Driver ps dstate m -> dstate
startDState :: dstate
}
data SomeMessage (st :: ps) where
SomeMessage :: Message ps st st' -> SomeMessage st
runPeerWithDriver
:: forall ps (st :: ps) pr dstate m a.
Monad m
=> Driver ps dstate m
-> Peer ps pr st m a
-> dstate
-> m (a, dstate)
runPeerWithDriver :: Driver ps dstate m -> Peer ps pr st m a -> dstate -> m (a, dstate)
runPeerWithDriver Driver{forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage :: forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage :: forall ps dstate (m :: * -> *).
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage, forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall ps dstate (m :: * -> *).
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage} =
(dstate -> Peer ps pr st m a -> m (a, dstate))
-> Peer ps pr st m a -> dstate -> m (a, dstate)
forall a b c. (a -> b -> c) -> b -> a -> c
flip dstate -> Peer ps pr st m a -> m (a, dstate)
forall (st' :: ps). dstate -> Peer ps pr st' m a -> m (a, dstate)
go
where
go :: forall st'.
dstate
-> Peer ps pr st' m a
-> m (a, dstate)
go :: dstate -> Peer ps pr st' m a -> m (a, dstate)
go dstate
dstate (Effect m (Peer ps pr st' m a)
k) = m (Peer ps pr st' m a)
k m (Peer ps pr st' m a)
-> (Peer ps pr st' m a -> m (a, dstate)) -> m (a, dstate)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= dstate -> Peer ps pr st' m a -> m (a, dstate)
forall (st' :: ps). dstate -> Peer ps pr st' m a -> m (a, dstate)
go dstate
dstate
go dstate
dstate (Done NobodyHasAgency st'
_ a
x) = (a, dstate) -> m (a, dstate)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
x, dstate
dstate)
go dstate
dstate (Yield WeHaveAgency pr st'
stok Message ps st' st'
msg Peer ps pr st' m a
k) = do
WeHaveAgency pr st' -> Message ps st' st' -> m ()
forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage WeHaveAgency pr st'
stok Message ps st' st'
msg
dstate -> Peer ps pr st' m a -> m (a, dstate)
forall (st' :: ps). dstate -> Peer ps pr st' m a -> m (a, dstate)
go dstate
dstate Peer ps pr st' m a
k
go dstate
dstate (Await TheyHaveAgency pr st'
stok forall (st' :: ps). Message ps st' st' -> Peer ps pr st' m a
k) = do
(SomeMessage Message ps st' st'
msg, dstate
dstate') <- TheyHaveAgency pr st' -> dstate -> m (SomeMessage st', dstate)
forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage TheyHaveAgency pr st'
stok dstate
dstate
dstate -> Peer ps pr st' m a -> m (a, dstate)
forall (st' :: ps). dstate -> Peer ps pr st' m a -> m (a, dstate)
go dstate
dstate' (Message ps st' st' -> Peer ps pr st' m a
forall (st' :: ps). Message ps st' st' -> Peer ps pr st' m a
k Message ps st' st'
msg)
runPipelinedPeerWithDriver
:: forall ps (st :: ps) pr dstate m a.
MonadAsync m
=> Driver ps dstate m
-> PeerPipelined ps pr st m a
-> dstate
-> m (a, dstate)
runPipelinedPeerWithDriver :: Driver ps dstate m
-> PeerPipelined ps pr st m a -> dstate -> m (a, dstate)
runPipelinedPeerWithDriver Driver ps dstate m
driver (PeerPipelined PeerSender ps pr st 'Z c m a
peer) dstate
dstate0 = do
TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue <- STM m (TQueue m (ReceiveHandler dstate ps pr m c))
-> m (TQueue m (ReceiveHandler dstate ps pr m c))
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically STM m (TQueue m (ReceiveHandler dstate ps pr m c))
forall (m :: * -> *) a. MonadSTM m => STM m (TQueue m a)
newTQueue
TQueue m (c, dstate)
collectQueue <- STM m (TQueue m (c, dstate)) -> m (TQueue m (c, dstate))
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically STM m (TQueue m (c, dstate))
forall (m :: * -> *) a. MonadSTM m => STM m (TQueue m a)
newTQueue
(a, dstate)
a <- TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate) -> Driver ps dstate m -> m Void
forall ps (pr :: PeerRole) dstate (m :: * -> *) c.
(MonadSTM m, MonadThread m) =>
TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate) -> Driver ps dstate m -> m Void
runPipelinedPeerReceiverQueue TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue TQueue m (c, dstate)
collectQueue Driver ps dstate m
driver
m Void -> m (a, dstate) -> m (a, dstate)
forall x. m Void -> m x -> m x
`withAsyncLoop`
TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate)
-> Driver ps dstate m
-> PeerSender ps pr st 'Z c m a
-> dstate
-> m (a, dstate)
forall ps (st :: ps) (pr :: PeerRole) dstate c (m :: * -> *) a.
(MonadSTM m, MonadThread m) =>
TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate)
-> Driver ps dstate m
-> PeerSender ps pr st 'Z c m a
-> dstate
-> m (a, dstate)
runPipelinedPeerSender TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue TQueue m (c, dstate)
collectQueue Driver ps dstate m
driver
PeerSender ps pr st 'Z c m a
peer dstate
dstate0
(a, dstate) -> m (a, dstate)
forall (m :: * -> *) a. Monad m => a -> m a
return (a, dstate)
a
where
withAsyncLoop :: m Void -> m x -> m x
withAsyncLoop :: m Void -> m x -> m x
withAsyncLoop m Void
left m x
right = do
Either Void x
res <- m Void -> m x -> m (Either Void x)
forall (m :: * -> *) a b.
MonadAsync m =>
m a -> m b -> m (Either a b)
race m Void
left m x
right
case Either Void x
res of
Left Void
v -> case Void
v of {}
Right x
a -> x -> m x
forall (m :: * -> *) a. Monad m => a -> m a
return x
a
data ReceiveHandler dstate ps pr m c where
ReceiveHandler :: MaybeDState dstate n
-> PeerReceiver ps pr (st :: ps) (st' :: ps) m c
-> ReceiveHandler dstate ps pr m c
data MaybeDState dstate (n :: N) where
HasDState :: dstate -> MaybeDState dstate Z
NoDState :: MaybeDState dstate (S n)
runPipelinedPeerSender
:: forall ps (st :: ps) pr dstate c m a.
( MonadSTM m
, MonadThread m
)
=> TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate)
-> Driver ps dstate m
-> PeerSender ps pr st Z c m a
-> dstate
-> m (a, dstate)
runPipelinedPeerSender :: TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate)
-> Driver ps dstate m
-> PeerSender ps pr st 'Z c m a
-> dstate
-> m (a, dstate)
runPipelinedPeerSender TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue TQueue m (c, dstate)
collectQueue
Driver{forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage :: forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage :: forall ps dstate (m :: * -> *).
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage, forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall ps dstate (m :: * -> *).
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage}
PeerSender ps pr st 'Z c m a
peer dstate
dstate0 = do
ThreadId m
threadId <- m (ThreadId m)
forall (m :: * -> *). MonadThread m => m (ThreadId m)
myThreadId
ThreadId m -> String -> m ()
forall (m :: * -> *). MonadThread m => ThreadId m -> String -> m ()
labelThread ThreadId m
threadId String
"pipeliend-peer-seneder"
Nat 'Z
-> MaybeDState dstate 'Z
-> PeerSender ps pr st 'Z c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat 'Z
forall (n :: N). ('Z ~ n) => Nat n
Zero (dstate -> MaybeDState dstate 'Z
forall dstate. dstate -> MaybeDState dstate 'Z
HasDState dstate
dstate0) PeerSender ps pr st 'Z c m a
peer
where
go :: forall st' n.
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go :: Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat n
n MaybeDState dstate n
dstate (SenderEffect m (PeerSender ps pr st' n c m a)
k) = m (PeerSender ps pr st' n c m a)
k m (PeerSender ps pr st' n c m a)
-> (PeerSender ps pr st' n c m a -> m (a, dstate)) -> m (a, dstate)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat n
n MaybeDState dstate n
dstate
go Nat n
Zero (HasDState dstate
dstate) (SenderDone NobodyHasAgency st'
_ a
x) = (a, dstate) -> m (a, dstate)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
x, dstate
dstate)
go Nat n
Zero MaybeDState dstate n
dstate (SenderYield WeHaveAgency pr st'
stok Message ps st' st'
msg PeerSender ps pr st' 'Z c m a
k) = do
WeHaveAgency pr st' -> Message ps st' st' -> m ()
forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage WeHaveAgency pr st'
stok Message ps st' st'
msg
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat n
forall (n :: N). ('Z ~ n) => Nat n
Zero MaybeDState dstate n
dstate PeerSender ps pr st' n c m a
PeerSender ps pr st' 'Z c m a
k
go Nat n
Zero (HasDState dstate
dstate) (SenderAwait TheyHaveAgency pr st'
stok forall (st' :: ps).
Message ps st' st' -> PeerSender ps pr st' 'Z c m a
k) = do
(SomeMessage Message ps st' st'
msg, dstate
dstate') <- TheyHaveAgency pr st' -> dstate -> m (SomeMessage st', dstate)
forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage TheyHaveAgency pr st'
stok dstate
dstate
Nat 'Z
-> MaybeDState dstate 'Z
-> PeerSender ps pr st' 'Z c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat 'Z
forall (n :: N). ('Z ~ n) => Nat n
Zero (dstate -> MaybeDState dstate 'Z
forall dstate. dstate -> MaybeDState dstate 'Z
HasDState dstate
dstate') (Message ps st' st' -> PeerSender ps pr st' 'Z c m a
forall (st' :: ps).
Message ps st' st' -> PeerSender ps pr st' 'Z c m a
k Message ps st' st'
msg)
go Nat n
n MaybeDState dstate n
dstate (SenderPipeline WeHaveAgency pr st'
stok Message ps st' st'
msg PeerReceiver ps pr st' st'' m c
receiver PeerSender ps pr st'' ('S n) c m a
k) = do
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TQueue m (ReceiveHandler dstate ps pr m c)
-> ReceiveHandler dstate ps pr m c -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TQueue m a -> a -> STM m ()
writeTQueue TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue (MaybeDState dstate n
-> PeerReceiver ps pr st' st'' m c
-> ReceiveHandler dstate ps pr m c
forall dstate (n :: N) ps (pr :: PeerRole) (st :: ps) (st' :: ps)
(m :: * -> *) c.
MaybeDState dstate n
-> PeerReceiver ps pr st st' m c -> ReceiveHandler dstate ps pr m c
ReceiveHandler MaybeDState dstate n
dstate PeerReceiver ps pr st' st'' m c
receiver))
WeHaveAgency pr st' -> Message ps st' st' -> m ()
forall (pr :: PeerRole) (st :: ps) (st' :: ps).
PeerHasAgency pr st -> Message ps st st' -> m ()
sendMessage WeHaveAgency pr st'
stok Message ps st' st'
msg
Nat ('S n)
-> MaybeDState dstate ('S n)
-> PeerSender ps pr st'' ('S n) c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go (Nat n -> Nat ('S n)
forall (m :: N) (n :: N). (m ~ 'S n) => Nat n -> Nat m
Succ Nat n
n) MaybeDState dstate ('S n)
forall dstate (n :: N). MaybeDState dstate ('S n)
NoDState PeerSender ps pr st'' ('S n) c m a
k
go (Succ Nat n
n) MaybeDState dstate n
NoDState (SenderCollect Maybe (PeerSender ps pr st' ('S n) c m a)
Nothing c -> PeerSender ps pr st' n c m a
k) = do
(c
c, dstate
dstate) <- STM m (c, dstate) -> m (c, dstate)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TQueue m (c, dstate) -> STM m (c, dstate)
forall (m :: * -> *) a. MonadSTM m => TQueue m a -> STM m a
readTQueue TQueue m (c, dstate)
collectQueue)
case Nat n
n of
Nat n
Zero -> Nat 'Z
-> MaybeDState dstate 'Z
-> PeerSender ps pr st' 'Z c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat 'Z
forall (n :: N). ('Z ~ n) => Nat n
Zero (dstate -> MaybeDState dstate 'Z
forall dstate. dstate -> MaybeDState dstate 'Z
HasDState dstate
dstate) (c -> PeerSender ps pr st' n c m a
k c
c)
Succ Nat n
n' -> Nat ('S n)
-> MaybeDState dstate ('S n)
-> PeerSender ps pr st' ('S n) c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go (Nat n -> Nat ('S n)
forall (m :: N) (n :: N). (m ~ 'S n) => Nat n -> Nat m
Succ Nat n
n') MaybeDState dstate ('S n)
forall dstate (n :: N). MaybeDState dstate ('S n)
NoDState (c -> PeerSender ps pr st' n c m a
k c
c)
go (Succ Nat n
n) MaybeDState dstate n
NoDState (SenderCollect (Just PeerSender ps pr st' ('S n) c m a
k') c -> PeerSender ps pr st' n c m a
k) = do
Maybe (c, dstate)
mc <- STM m (Maybe (c, dstate)) -> m (Maybe (c, dstate))
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TQueue m (c, dstate) -> STM m (Maybe (c, dstate))
forall (m :: * -> *) a. MonadSTM m => TQueue m a -> STM m (Maybe a)
tryReadTQueue TQueue m (c, dstate)
collectQueue)
case Maybe (c, dstate)
mc of
Maybe (c, dstate)
Nothing -> Nat ('S n)
-> MaybeDState dstate ('S n)
-> PeerSender ps pr st' ('S n) c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go (Nat n -> Nat ('S n)
forall (m :: N) (n :: N). (m ~ 'S n) => Nat n -> Nat m
Succ Nat n
n) MaybeDState dstate ('S n)
forall dstate (n :: N). MaybeDState dstate ('S n)
NoDState PeerSender ps pr st' ('S n) c m a
k'
Just (c
c, dstate
dstate) ->
case Nat n
n of
Nat n
Zero -> Nat 'Z
-> MaybeDState dstate 'Z
-> PeerSender ps pr st' 'Z c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go Nat 'Z
forall (n :: N). ('Z ~ n) => Nat n
Zero (dstate -> MaybeDState dstate 'Z
forall dstate. dstate -> MaybeDState dstate 'Z
HasDState dstate
dstate) (c -> PeerSender ps pr st' n c m a
k c
c)
Succ Nat n
n' -> Nat ('S n)
-> MaybeDState dstate ('S n)
-> PeerSender ps pr st' ('S n) c m a
-> m (a, dstate)
forall (st' :: ps) (n :: N).
Nat n
-> MaybeDState dstate n
-> PeerSender ps pr st' n c m a
-> m (a, dstate)
go (Nat n -> Nat ('S n)
forall (m :: N) (n :: N). (m ~ 'S n) => Nat n -> Nat m
Succ Nat n
n') MaybeDState dstate ('S n)
forall dstate (n :: N). MaybeDState dstate ('S n)
NoDState (c -> PeerSender ps pr st' n c m a
k c
c)
runPipelinedPeerReceiverQueue
:: forall ps pr dstate m c.
( MonadSTM m
, MonadThread m
)
=> TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate)
-> Driver ps dstate m
-> m Void
runPipelinedPeerReceiverQueue :: TQueue m (ReceiveHandler dstate ps pr m c)
-> TQueue m (c, dstate) -> Driver ps dstate m -> m Void
runPipelinedPeerReceiverQueue TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue TQueue m (c, dstate)
collectQueue
driver :: Driver ps dstate m
driver@Driver{dstate
startDState :: dstate
startDState :: forall ps dstate (m :: * -> *). Driver ps dstate m -> dstate
startDState} = do
ThreadId m
threadId <- m (ThreadId m)
forall (m :: * -> *). MonadThread m => m (ThreadId m)
myThreadId
ThreadId m -> String -> m ()
forall (m :: * -> *). MonadThread m => ThreadId m -> String -> m ()
labelThread ThreadId m
threadId String
"pipelined-recevier-queue"
dstate -> m Void
go dstate
startDState
where
go :: dstate -> m Void
go :: dstate -> m Void
go dstate
receiverDState = do
ReceiveHandler MaybeDState dstate n
senderDState PeerReceiver ps pr st st' m c
receiver
<- STM m (ReceiveHandler dstate ps pr m c)
-> m (ReceiveHandler dstate ps pr m c)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TQueue m (ReceiveHandler dstate ps pr m c)
-> STM m (ReceiveHandler dstate ps pr m c)
forall (m :: * -> *) a. MonadSTM m => TQueue m a -> STM m a
readTQueue TQueue m (ReceiveHandler dstate ps pr m c)
receiveQueue)
let dstate :: dstate
dstate = case (MaybeDState dstate n
senderDState, dstate
receiverDState) of
(HasDState dstate
t, dstate
_) -> dstate
t
(MaybeDState dstate n
NoDState, dstate
t) -> dstate
t
x :: (c, dstate)
x@(!c
_c, !dstate
dstate') <- Driver ps dstate m
-> dstate -> PeerReceiver ps pr st st' m c -> m (c, dstate)
forall ps (st :: ps) (stdone :: ps) (pr :: PeerRole) dstate
(m :: * -> *) c.
Monad m =>
Driver ps dstate m
-> dstate -> PeerReceiver ps pr st stdone m c -> m (c, dstate)
runPipelinedPeerReceiver Driver ps dstate m
driver dstate
dstate PeerReceiver ps pr st st' m c
receiver
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TQueue m (c, dstate) -> (c, dstate) -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TQueue m a -> a -> STM m ()
writeTQueue TQueue m (c, dstate)
collectQueue (c, dstate)
x)
dstate -> m Void
go dstate
dstate'
runPipelinedPeerReceiver
:: forall ps (st :: ps) (stdone :: ps) pr dstate m c.
Monad m
=> Driver ps dstate m
-> dstate
-> PeerReceiver ps pr (st :: ps) (stdone :: ps) m c
-> m (c, dstate)
runPipelinedPeerReceiver :: Driver ps dstate m
-> dstate -> PeerReceiver ps pr st stdone m c -> m (c, dstate)
runPipelinedPeerReceiver Driver{forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage :: forall ps dstate (m :: * -> *).
Driver ps dstate m
-> forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage} = dstate -> PeerReceiver ps pr st stdone m c -> m (c, dstate)
forall (st' :: ps) (st'' :: ps).
dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
go
where
go :: forall st' st''.
dstate
-> PeerReceiver ps pr st' st'' m c
-> m (c, dstate)
go :: dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
go dstate
dstate (ReceiverEffect m (PeerReceiver ps pr st' st'' m c)
k) = m (PeerReceiver ps pr st' st'' m c)
k m (PeerReceiver ps pr st' st'' m c)
-> (PeerReceiver ps pr st' st'' m c -> m (c, dstate))
-> m (c, dstate)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
forall (st' :: ps) (st'' :: ps).
dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
go dstate
dstate
go dstate
dstate (ReceiverDone c
x) = (c, dstate) -> m (c, dstate)
forall (m :: * -> *) a. Monad m => a -> m a
return (c
x, dstate
dstate)
go dstate
dstate (ReceiverAwait TheyHaveAgency pr st'
stok forall (st' :: ps).
Message ps st' st' -> PeerReceiver ps pr st' st'' m c
k) = do
(SomeMessage Message ps st' st'
msg, dstate
dstate') <- TheyHaveAgency pr st' -> dstate -> m (SomeMessage st', dstate)
forall (pr :: PeerRole) (st :: ps).
PeerHasAgency pr st -> dstate -> m (SomeMessage st, dstate)
recvMessage TheyHaveAgency pr st'
stok dstate
dstate
dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
forall (st' :: ps) (st'' :: ps).
dstate -> PeerReceiver ps pr st' st'' m c -> m (c, dstate)
go dstate
dstate' (Message ps st' st' -> PeerReceiver ps pr st' st'' m c
forall (st' :: ps).
Message ps st' st' -> PeerReceiver ps pr st' st'' m c
k Message ps st' st'
msg)