{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}

-- | Lamport clock network simulation.
-- 'ReplicaSim' provides 'Replica' and 'Clock' instances,
-- replicas may interchange data while they are connected in a 'NetworkSim'.
module RON.Event.Simulation (
    NetworkSimT,
    ReplicaSimT,
    runNetworkSimT,
    runReplicaSimT,
) where

import           RON.Prelude

import           Control.Monad.State.Strict (state)
import qualified Data.HashMap.Strict as HM

import           RON.Event (Event (..), Replica (Replica), ReplicaClock,
                            TimeVariety (Logical), advance, getEvents, getPid,
                            mkTime)
import           RON.Util.Word (Word60, ls60)

-- | Lamport clock simulation. Key is 'Replica'.
-- Non-present value is equivalent to (0, initial).
newtype NetworkSimT m a = NetworkSim (StateT (HashMap Replica Word60) m a)
    deriving (Functor (NetworkSimT m)
a -> NetworkSimT m a
Functor (NetworkSimT m)
-> (forall a. a -> NetworkSimT m a)
-> (forall a b.
    NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b)
-> (forall a b c.
    (a -> b -> c)
    -> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c)
-> (forall a b.
    NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b)
-> (forall a b.
    NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a)
-> Applicative (NetworkSimT m)
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a
NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b
(a -> b -> c)
-> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c
forall a. a -> NetworkSimT m a
forall a b. NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a
forall a b. NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
forall a b.
NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b
forall a b c.
(a -> b -> c)
-> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c
forall (m :: * -> *). Monad m => Functor (NetworkSimT m)
forall (m :: * -> *) a. Monad m => a -> NetworkSimT m a
forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a
forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a
$c<* :: forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m a
*> :: NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
$c*> :: forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
liftA2 :: (a -> b -> c)
-> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m c
<*> :: NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m (a -> b) -> NetworkSimT m a -> NetworkSimT m b
pure :: a -> NetworkSimT m a
$cpure :: forall (m :: * -> *) a. Monad m => a -> NetworkSimT m a
$cp1Applicative :: forall (m :: * -> *). Monad m => Functor (NetworkSimT m)
Applicative, a -> NetworkSimT m b -> NetworkSimT m a
(a -> b) -> NetworkSimT m a -> NetworkSimT m b
(forall a b. (a -> b) -> NetworkSimT m a -> NetworkSimT m b)
-> (forall a b. a -> NetworkSimT m b -> NetworkSimT m a)
-> Functor (NetworkSimT m)
forall a b. a -> NetworkSimT m b -> NetworkSimT m a
forall a b. (a -> b) -> NetworkSimT m a -> NetworkSimT m b
forall (m :: * -> *) a b.
Functor m =>
a -> NetworkSimT m b -> NetworkSimT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> NetworkSimT m a -> NetworkSimT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> NetworkSimT m b -> NetworkSimT m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> NetworkSimT m b -> NetworkSimT m a
fmap :: (a -> b) -> NetworkSimT m a -> NetworkSimT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> NetworkSimT m a -> NetworkSimT m b
Functor, Applicative (NetworkSimT m)
a -> NetworkSimT m a
Applicative (NetworkSimT m)
-> (forall a b.
    NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b)
-> (forall a b.
    NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b)
-> (forall a. a -> NetworkSimT m a)
-> Monad (NetworkSimT m)
NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
forall a. a -> NetworkSimT m a
forall a b. NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
forall a b.
NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b
forall (m :: * -> *). Monad m => Applicative (NetworkSimT m)
forall (m :: * -> *) a. Monad m => a -> NetworkSimT m a
forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> NetworkSimT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> NetworkSimT m a
>> :: NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> NetworkSimT m b -> NetworkSimT m b
>>= :: NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
NetworkSimT m a -> (a -> NetworkSimT m b) -> NetworkSimT m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (NetworkSimT m)
Monad, MonadError e)

instance MonadTrans NetworkSimT where
    lift :: m a -> NetworkSimT m a
lift = StateT (HashMap Replica Word60) m a -> NetworkSimT m a
forall (m :: * -> *) a.
StateT (HashMap Replica Word60) m a -> NetworkSimT m a
NetworkSim (StateT (HashMap Replica Word60) m a -> NetworkSimT m a)
-> (m a -> StateT (HashMap Replica Word60) m a)
-> m a
-> NetworkSimT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> StateT (HashMap Replica Word60) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

-- | ReplicaSim inside Lamport clock simulation.
newtype ReplicaSimT m a = ReplicaSim (ReaderT Replica (NetworkSimT m) a)
    deriving (Functor (ReplicaSimT m)
a -> ReplicaSimT m a
Functor (ReplicaSimT m)
-> (forall a. a -> ReplicaSimT m a)
-> (forall a b.
    ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b)
-> (forall a b c.
    (a -> b -> c)
    -> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c)
-> (forall a b.
    ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b)
-> (forall a b.
    ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a)
-> Applicative (ReplicaSimT m)
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a
ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
(a -> b -> c)
-> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c
forall a. a -> ReplicaSimT m a
forall a b. ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a
forall a b. ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
forall a b.
ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
forall a b c.
(a -> b -> c)
-> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c
forall (m :: * -> *). Monad m => Functor (ReplicaSimT m)
forall (m :: * -> *) a. Monad m => a -> ReplicaSimT m a
forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a
forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a
$c<* :: forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m a
*> :: ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
$c*> :: forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
liftA2 :: (a -> b -> c)
-> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m c
<*> :: ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
pure :: a -> ReplicaSimT m a
$cpure :: forall (m :: * -> *) a. Monad m => a -> ReplicaSimT m a
$cp1Applicative :: forall (m :: * -> *). Monad m => Functor (ReplicaSimT m)
Applicative, a -> ReplicaSimT m b -> ReplicaSimT m a
(a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
(forall a b. (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b)
-> (forall a b. a -> ReplicaSimT m b -> ReplicaSimT m a)
-> Functor (ReplicaSimT m)
forall a b. a -> ReplicaSimT m b -> ReplicaSimT m a
forall a b. (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
forall (m :: * -> *) a b.
Functor m =>
a -> ReplicaSimT m b -> ReplicaSimT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> ReplicaSimT m b -> ReplicaSimT m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> ReplicaSimT m b -> ReplicaSimT m a
fmap :: (a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> ReplicaSimT m a -> ReplicaSimT m b
Functor, Applicative (ReplicaSimT m)
a -> ReplicaSimT m a
Applicative (ReplicaSimT m)
-> (forall a b.
    ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b)
-> (forall a b.
    ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b)
-> (forall a. a -> ReplicaSimT m a)
-> Monad (ReplicaSimT m)
ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
forall a. a -> ReplicaSimT m a
forall a b. ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
forall a b.
ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b
forall (m :: * -> *). Monad m => Applicative (ReplicaSimT m)
forall (m :: * -> *) a. Monad m => a -> ReplicaSimT m a
forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> ReplicaSimT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> ReplicaSimT m a
>> :: ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> ReplicaSimT m b -> ReplicaSimT m b
>>= :: ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
ReplicaSimT m a -> (a -> ReplicaSimT m b) -> ReplicaSimT m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (ReplicaSimT m)
Monad, MonadError e)

instance MonadTrans ReplicaSimT where
    lift :: m a -> ReplicaSimT m a
lift = ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a
forall (m :: * -> *) a.
ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a
ReplicaSim (ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a)
-> (m a -> ReaderT Replica (NetworkSimT m) a)
-> m a
-> ReplicaSimT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NetworkSimT m a -> ReaderT Replica (NetworkSimT m) a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NetworkSimT m a -> ReaderT Replica (NetworkSimT m) a)
-> (m a -> NetworkSimT m a)
-> m a
-> ReaderT Replica (NetworkSimT m) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> NetworkSimT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

instance Monad m => ReplicaClock (ReplicaSimT m) where
    getPid :: ReplicaSimT m Replica
getPid = ReaderT Replica (NetworkSimT m) Replica -> ReplicaSimT m Replica
forall (m :: * -> *) a.
ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a
ReplicaSim ReaderT Replica (NetworkSimT m) Replica
forall r (m :: * -> *). MonadReader r m => m r
ask

    getEvents :: Word60 -> ReplicaSimT m [Event]
getEvents Word60
n' = ReaderT Replica (NetworkSimT m) [Event] -> ReplicaSimT m [Event]
forall (m :: * -> *) a.
ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a
ReplicaSim (ReaderT Replica (NetworkSimT m) [Event] -> ReplicaSimT m [Event])
-> ReaderT Replica (NetworkSimT m) [Event] -> ReplicaSimT m [Event]
forall a b. (a -> b) -> a -> b
$ do
        Replica
replica <- ReaderT Replica (NetworkSimT m) Replica
forall r (m :: * -> *). MonadReader r m => m r
ask
        (Word60
t0, Word60
t1) <-
            NetworkSimT m (Word60, Word60)
-> ReaderT Replica (NetworkSimT m) (Word60, Word60)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NetworkSimT m (Word60, Word60)
 -> ReaderT Replica (NetworkSimT m) (Word60, Word60))
-> NetworkSimT m (Word60, Word60)
-> ReaderT Replica (NetworkSimT m) (Word60, Word60)
forall a b. (a -> b) -> a -> b
$ StateT (HashMap Replica Word60) m (Word60, Word60)
-> NetworkSimT m (Word60, Word60)
forall (m :: * -> *) a.
StateT (HashMap Replica Word60) m a -> NetworkSimT m a
NetworkSim (StateT (HashMap Replica Word60) m (Word60, Word60)
 -> NetworkSimT m (Word60, Word60))
-> StateT (HashMap Replica Word60) m (Word60, Word60)
-> NetworkSimT m (Word60, Word60)
forall a b. (a -> b) -> a -> b
$ (HashMap Replica Word60
 -> ((Word60, Word60), HashMap Replica Word60))
-> StateT (HashMap Replica Word60) m (Word60, Word60)
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((HashMap Replica Word60
  -> ((Word60, Word60), HashMap Replica Word60))
 -> StateT (HashMap Replica Word60) m (Word60, Word60))
-> (HashMap Replica Word60
    -> ((Word60, Word60), HashMap Replica Word60))
-> StateT (HashMap Replica Word60) m (Word60, Word60)
forall a b. (a -> b) -> a -> b
$ \HashMap Replica Word60
replicaStates -> let
                t0orig :: Word60
t0orig = Word60 -> Replica -> HashMap Replica Word60 -> Word60
forall k v. (Eq k, Hashable k) => v -> k -> HashMap k v -> v
HM.lookupDefault (Word64 -> Word60
ls60 Word64
0) Replica
replica HashMap Replica Word60
replicaStates
                Replica Word64
r = Replica
replica
                randomLeap :: Word60
randomLeap =
                    Word64 -> Word60
ls60 (Word64 -> Word60) -> (Int -> Word64) -> Int -> Word60
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word60) -> Int -> Word60
forall a b. (a -> b) -> a -> b
$ (Word60, Word60, Word64) -> Int
forall a. Hashable a => a -> Int
hash (Word60
t0orig, Word60
n, Word64
r) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
0x10000
                t0 :: Word60
t0 = Word60
t0orig Word60 -> Word60 -> Word60
forall a. Num a => a -> a -> a
+ Word60
randomLeap
                t1 :: Word60
t1 = Word60
t0 Word60 -> Word60 -> Word60
forall a. Num a => a -> a -> a
+ Word60
n
                in ((Word60
t0, Word60
t1), Replica
-> Word60 -> HashMap Replica Word60 -> HashMap Replica Word60
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert Replica
replica Word60
t1 HashMap Replica Word60
replicaStates)
        [Event] -> ReaderT Replica (NetworkSimT m) [Event]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Event :: Time -> Replica -> Event
Event{time :: Time
time = TimeVariety -> Word60 -> Time
mkTime TimeVariety
Logical Word60
t, Replica
replica :: Replica
replica :: Replica
replica} | Word60
t <- [Word60 -> Word60
forall a. Enum a => a -> a
succ Word60
t0 .. Word60
t1]]
      where
        n :: Word60
n = Word60 -> Word60 -> Word60
forall a. Ord a => a -> a -> a
max Word60
n' (Word64 -> Word60
ls60 Word64
1)

    advance :: Word60 -> ReplicaSimT m ()
advance Word60
time = ReaderT Replica (NetworkSimT m) () -> ReplicaSimT m ()
forall (m :: * -> *) a.
ReaderT Replica (NetworkSimT m) a -> ReplicaSimT m a
ReplicaSim (ReaderT Replica (NetworkSimT m) () -> ReplicaSimT m ())
-> ReaderT Replica (NetworkSimT m) () -> ReplicaSimT m ()
forall a b. (a -> b) -> a -> b
$ do
        Replica
rid <- ReaderT Replica (NetworkSimT m) Replica
forall r (m :: * -> *). MonadReader r m => m r
ask
        NetworkSimT m () -> ReaderT Replica (NetworkSimT m) ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NetworkSimT m () -> ReaderT Replica (NetworkSimT m) ())
-> ((HashMap Replica Word60 -> HashMap Replica Word60)
    -> NetworkSimT m ())
-> (HashMap Replica Word60 -> HashMap Replica Word60)
-> ReaderT Replica (NetworkSimT m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateT (HashMap Replica Word60) m () -> NetworkSimT m ()
forall (m :: * -> *) a.
StateT (HashMap Replica Word60) m a -> NetworkSimT m a
NetworkSim (StateT (HashMap Replica Word60) m () -> NetworkSimT m ())
-> ((HashMap Replica Word60 -> HashMap Replica Word60)
    -> StateT (HashMap Replica Word60) m ())
-> (HashMap Replica Word60 -> HashMap Replica Word60)
-> NetworkSimT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashMap Replica Word60 -> HashMap Replica Word60)
-> StateT (HashMap Replica Word60) m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify' ((HashMap Replica Word60 -> HashMap Replica Word60)
 -> ReaderT Replica (NetworkSimT m) ())
-> (HashMap Replica Word60 -> HashMap Replica Word60)
-> ReaderT Replica (NetworkSimT m) ()
forall a b. (a -> b) -> a -> b
$ (Maybe Word60 -> Maybe Word60)
-> Replica -> HashMap Replica Word60 -> HashMap Replica Word60
forall k v.
(Eq k, Hashable k) =>
(Maybe v -> Maybe v) -> k -> HashMap k v -> HashMap k v
HM.alter (Word60 -> Maybe Word60
forall a. a -> Maybe a
Just (Word60 -> Maybe Word60)
-> (Maybe Word60 -> Word60) -> Maybe Word60 -> Maybe Word60
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Word60 -> Word60
advancePS) Replica
rid
      where
        advancePS :: Maybe Word60 -> Word60
advancePS = \case
            Maybe Word60
Nothing      -> Word60
time
            Just Word60
current -> Word60 -> Word60 -> Word60
forall a. Ord a => a -> a -> a
max Word60
time Word60
current

instance MonadFail m => MonadFail (ReplicaSimT m) where
    fail :: String -> ReplicaSimT m a
fail = m a -> ReplicaSimT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ReplicaSimT m a)
-> (String -> m a) -> String -> ReplicaSimT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail

-- | Execute network simulation
--
-- Usage:
--
-- @
-- 'runExceptT' . runNetworkSimT $ do
--     'runReplicaSimT' r1 $ do
--         actions...
--     'runReplicaSimT' r2 $ do
--         actions...
--     'runReplicaSimT' r1 $ ...
-- @
--
-- Each 'runNetworkSimT' starts its own networks.
-- One shouldn't use in one network events generated in another.
runNetworkSimT :: Monad m => NetworkSimT m a -> m a
runNetworkSimT :: NetworkSimT m a -> m a
runNetworkSimT (NetworkSim StateT (HashMap Replica Word60) m a
action) = StateT (HashMap Replica Word60) m a
-> HashMap Replica Word60 -> m a
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT StateT (HashMap Replica Word60) m a
action HashMap Replica Word60
forall a. Monoid a => a
mempty

runReplicaSimT :: Replica -> ReplicaSimT m a -> NetworkSimT m a
runReplicaSimT :: Replica -> ReplicaSimT m a -> NetworkSimT m a
runReplicaSimT Replica
rid (ReplicaSim ReaderT Replica (NetworkSimT m) a
action) = ReaderT Replica (NetworkSimT m) a -> Replica -> NetworkSimT m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT Replica (NetworkSimT m) a
action Replica
rid