diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+
+Version 0.3
+-----
+
+* Started using Samadi's algorithm to synchronize the global virtual time.
+
+* The local processes must call registerDIO to connect to the time server.
+
+* Increased the default synchronization time-out and delay.
+
+* Increased the default log size threshold.
diff --git a/Simulation/Aivika/Distributed/Optimistic/DIO.hs b/Simulation/Aivika/Distributed/Optimistic/DIO.hs
--- a/Simulation/Aivika/Distributed/Optimistic/DIO.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/DIO.hs
@@ -21,6 +21,7 @@
         timeServerId,
         logDIO,
         terminateDIO,
+        registerDIO,
         unregisterDIO) where
 
 import Control.Monad
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/DIO.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/DIO.hs
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/DIO.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/DIO.hs
@@ -18,6 +18,7 @@
         runDIO,
         defaultDIOParams,
         terminateDIO,
+        registerDIO,
         unregisterDIO,
         dioParams,
         messageChannel,
@@ -128,9 +129,9 @@
 defaultDIOParams :: DIOParams
 defaultDIOParams =
   DIOParams { dioLoggingPriority = WARNING,
-              dioUndoableLogSizeThreshold = 500000,
+              dioUndoableLogSizeThreshold = 1000000,
               dioOutputMessageQueueSizeThreshold = 10000,
-              dioSyncTimeout = 5000000,
+              dioSyncTimeout = 60000000,
               dioAllowPrematureIO = False,
               dioAllowProcessingOutdatedMessage = False
             }
@@ -161,6 +162,16 @@
      liftDistributedUnsafe $
        DP.send receiver (TerminateTimeServerMessage sender)
 
+-- | Register the simulation process in the time server, which
+-- requires some initial quorum to start synchronizing the global time.
+registerDIO :: DIO ()
+registerDIO =
+  do logDIO INFO "Registering the simulation process..."
+     sender   <- messageInboxId
+     receiver <- timeServerId
+     liftDistributedUnsafe $
+       DP.send receiver (RegisterLocalProcessMessage sender)
+
 -- | Unregister the simulation process from the time server
 -- without affecting the processes in other nodes connected to
 -- the corresponding time server.
@@ -188,10 +199,6 @@
                logProcess ps INFO "Terminating the inbox process..."
                ---
                DP.terminate
-     ---
-     logProcess ps INFO "Registering the simulation process..."
-     ---
-     DP.send serverId (RegisterLocalProcessMessage inboxId)
      return (inboxId, unDIO m DIOContext { dioChannel = ch,
                                            dioInboxId = inboxId,
                                            dioTimeServerId = serverId,
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/Event.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/Event.hs
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/Event.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/Event.hs
@@ -42,6 +42,7 @@
 import Simulation.Aivika.Distributed.Optimistic.Internal.TimeWarp
 import {-# SOURCE #-} Simulation.Aivika.Distributed.Optimistic.Internal.InputMessageQueue
 import {-# SOURCE #-} Simulation.Aivika.Distributed.Optimistic.Internal.OutputMessageQueue
+import Simulation.Aivika.Distributed.Optimistic.Internal.TransientMessageQueue
 import Simulation.Aivika.Distributed.Optimistic.Internal.UndoableLog
 import {-# SOURCE #-} qualified Simulation.Aivika.Distributed.Optimistic.Internal.Ref as R
 
@@ -58,6 +59,8 @@
                  -- ^ the input message queue
                  queueOutputMessages :: OutputMessageQueue,
                  -- ^ the output message queue
+                 queueTransientMessages :: TransientMessageQueue,
+                 -- ^ the transient message queue
                  queueLog :: UndoableLog,
                  -- ^ the undoable log of operations
                  queuePQ :: R.Ref (PQ.PriorityQueue (Point DIO -> DIO ())),
@@ -68,14 +71,8 @@
                  -- ^ the actual time of the event queue
                  queueGlobalTime :: IORef Double,
                  -- ^ the global time
-                 queueLocalTime :: IORef Double,
-                 -- ^ the long-term queue local time
-                 queueLocalTime0 :: IORef Double,
-                 -- ^ the short-term queue local time
-                 queueLocalTimeTimestamp :: IORef UTCTime,
-                 -- ^ the queue local time timestamp
-                 queueLocalTimeInterval :: NominalDiffTime
-                 -- ^ the queue local time interval for updating
+                 queueInFind :: IORef Bool
+                 -- ^ whether the queue is in find mode
                }
 
   newEventQueue specs =
@@ -84,23 +81,19 @@
        gt <- liftIOUnsafe $ newIORef $ spcStartTime specs
        pq <- R.newRef0 PQ.emptyQueue
        log <- newUndoableLog
-       output <- newOutputMessageQueue
+       transient <- newTransientMessageQueue
+       output <- newOutputMessageQueue $ enqueueTransientMessage transient
        input <- newInputMessageQueue log rollbackEventPre rollbackEventPost rollbackEventTime
-       loct <- liftIOUnsafe $ newIORef $ spcStartTime specs
-       loct0 <- liftIOUnsafe $ newIORef $ spcStartTime specs
-       loctstamp <- liftIOUnsafe $ getCurrentTime >>= newIORef
-       locdt <- fmap (fromRational . microsecondsToSeconds . dioSyncTimeout) dioParams 
+       infind <- liftIOUnsafe $ newIORef False
        return EventQueue { queueInputMessages = input,
                            queueOutputMessages = output,
+                           queueTransientMessages = transient,
                            queueLog  = log,
                            queuePQ   = pq,
                            queueBusy = f,
                            queueTime = t,
                            queueGlobalTime = gt,
-                           queueLocalTime = loct,
-                           queueLocalTime0 = loct0,
-                           queueLocalTimeTimestamp = loctstamp,
-                           queueLocalTimeInterval = locdt }
+                           queueInFind = infind }
 
   enqueueEvent t (Event m) =
     Event $ \p ->
@@ -145,10 +138,7 @@
      --- logDIO DEBUG $
      ---   "Setting the queue time = " ++ show t
      ---
-     liftIOUnsafe $
-       do writeIORef (queueTime q) t
-          modifyIORef' (queueLocalTime q) (min t)
-          modifyIORef' (queueLocalTime0 q) (min t)
+     liftIOUnsafe $ writeIORef (queueTime q) t
      t0 <- liftIOUnsafe $ readIORef (queueGlobalTime q)
      when (t0 > t) $
        do ---
@@ -156,7 +146,6 @@
           ---   "Setting the global time = " ++ show t
           ---
           liftIOUnsafe $ writeIORef (queueGlobalTime q) t
-          invokeEvent p sendLocalTime
 
 -- | Return the current event time.
 currentEventTime :: Event DIO Double
@@ -298,8 +287,7 @@
 throttleMessageChannel :: TimeWarp DIO ()
 throttleMessageChannel =
   TimeWarp $ \p ->
-  do invokeEvent p updateLocalTime
-     invokeEvent p sendLocalTime
+  do invokeEvent p requestGlobalTime
      ch <- messageChannel
      dt <- fmap dioSyncTimeout dioParams
      liftIOUnsafe $
@@ -331,6 +319,8 @@
      --- invokeEvent p $
      ---   logMessage x
      ---
+     infind <- liftIOUnsafe $ readIORef (queueInFind q)
+     deliverAcknowledgmentMessage (acknowledgmentMessage infind m)
      t0 <- liftIOUnsafe $ readIORef (queueGlobalTime q)
      when (messageReceiveTime m < t0) $
        do f <- fmap dioAllowProcessingOutdatedMessage dioParams
@@ -346,6 +336,8 @@
      --- invokeEvent p $
      ---   logMessage x
      ---
+     infind <- liftIOUnsafe $ readIORef (queueInFind q)
+     deliverAcknowledgmentMessages $ map (acknowledgmentMessage infind) ms
      t0 <- liftIOUnsafe $ readIORef (queueGlobalTime q)
      forM_ ms $ \m ->
        do when (messageReceiveTime m < t0) $
@@ -355,31 +347,49 @@
                  else error "Received the outdated message: processChannelMessage"
           invokeTimeWarp p $
             enqueueMessage (queueInputMessages q) m
-processChannelMessage x@(GlobalTimeMessage globalTime) =
+processChannelMessage x@(AcknowledgmentQueueMessage m) =
   TimeWarp $ \p ->
   do let q = runEventQueue $ pointRun p
      ---
      --- invokeEvent p $
      ---   logMessage x
      ---
-     case globalTime of
-       Nothing -> return ()
-       Just t0 ->
-         invokeEvent p $
-         updateGlobalTime t0
-     invokeEvent p updateLocalTime
-     t <- invokeEvent p getLocalTime
+     liftIOUnsafe $
+       processAcknowledgmentMessage (queueTransientMessages q) m
+processChannelMessage x@(AcknowledgmentQueueMessageBulk ms) =
+  TimeWarp $ \p ->
+  do let q = runEventQueue $ pointRun p
+     ---
+     --- invokeEvent p $
+     ---   logMessage x
+     ---
+     liftIOUnsafe $
+       forM_ ms $
+       processAcknowledgmentMessage (queueTransientMessages q)
+processChannelMessage x@ComputeLocalTimeMessage =
+  TimeWarp $ \p ->
+  do let q = runEventQueue $ pointRun p
+     ---
+     --- invokeEvent p $
+     ---   logMessage x
+     ---
+     liftIOUnsafe $
+       writeIORef (queueInFind q) True
+     t' <- invokeEvent p getLocalTime
      sender   <- messageInboxId
      receiver <- timeServerId
      liftDistributedUnsafe $
-       DP.send receiver (GlobalTimeMessageResp sender t)
-processChannelMessage x@(LocalTimeMessageResp globalTime) =
+       DP.send receiver (LocalTimeMessage sender t')
+processChannelMessage x@(GlobalTimeMessage globalTime) =
   TimeWarp $ \p ->
   do let q = runEventQueue $ pointRun p
      ---
      --- invokeEvent p $
      ---   logMessage x
      ---
+     liftIOUnsafe $
+       do writeIORef (queueInFind q) False
+          resetAcknowledgmentMessageTime (queueTransientMessages q)
      invokeEvent p $
        updateGlobalTime globalTime
 processChannelMessage x@TerminateLocalProcessMessage =
@@ -391,12 +401,32 @@
      liftDistributedUnsafe $
        DP.terminate
 
+-- | Return the local minimum time.
+getLocalTime :: Event DIO Double
+getLocalTime =
+  Event $ \p ->
+  do let q = runEventQueue $ pointRun p
+     t1 <- liftIOUnsafe $ readIORef (queueTime q)
+     t2 <- liftIOUnsafe $ transientMessageQueueTime (queueTransientMessages q)
+     t3 <- liftIOUnsafe $ acknowledgmentMessageTime (queueTransientMessages q)
+     let t' = t1 `min` t2 `min` t3
+     ---
+     --- n <- liftIOUnsafe $ transientMessageQueueSize (queueTransientMessages q)
+     --- logDIO ERROR $
+     ---   "t = " ++ show (pointTime p) ++
+     ---   ": queue time = " ++ show t1 ++
+     ---   ", unacknowledged time = " ++ show t2 ++
+     ---   ", marked acknowledged time = " ++ show t3 ++
+     ---   ", transient queue size = " ++ show n ++
+     ---   " -> " ++ show t'
+     ---
+     return t'
+
 -- | Update the global time.
 updateGlobalTime :: Double -> Event DIO ()
 updateGlobalTime t =
   Event $ \p ->
   do let q = runEventQueue $ pointRun p
-     invokeEvent p updateLocalTime
      t' <- invokeEvent p getLocalTime
      if t > t'
        then logDIO WARNING $
@@ -407,6 +437,20 @@
                invokeEvent p $
                  reduceEvents t
 
+-- | Request for the global minimum time.
+requestGlobalTime :: Event DIO ()
+requestGlobalTime =
+  Event $ \p ->
+  do let q = runEventQueue $ pointRun p
+     ---
+     --- invokeEvent p $
+     ---   logRequestGlobalTime
+     ---
+     sender   <- messageInboxId
+     receiver <- timeServerId
+     liftDistributedUnsafe $
+       DP.send receiver (RequestGlobalTimeMessage sender)
+
 -- | Show the message.
 showMessage :: Message -> ShowS
 showMessage m =
@@ -463,16 +507,16 @@
        ", global t = " ++ (show t') ++
        ": synchronizing the local time in ring 0..."
 
--- | Log that the local time is sent to the time server.
-logSendLocalTime :: Event DIO ()
-logSendLocalTime =
+-- | Log that the global time is requested.
+logRequestGlobalTime :: Event DIO ()
+logRequestGlobalTime =
   Event $ \p ->
   do let q = runEventQueue $ pointRun p
      t' <- liftIOUnsafe $ readIORef (queueGlobalTime q)
      logDIO DEBUG $
        "t = " ++ (show $ pointTime p) ++
        ", global t = " ++ (show t') ++
-       ": sending the local time to the time server after delay..."
+       ": requesting for a new global time..."
 
 -- | Log an evidence of the premature IO.
 logPrematureIO :: Event DIO ()
@@ -520,48 +564,6 @@
                         "Detected a premature IO action at t = " ++
                         (show $ pointTime p) ++ ": liftIO"
 
--- | Update the local time.
-updateLocalTime :: Event DIO Bool
-updateLocalTime =
-  Event $ \p ->
-  do let q = runEventQueue $ pointRun p
-     timestamp0 <- liftIOUnsafe $ readIORef (queueLocalTimeTimestamp q)
-     timestamp  <- liftIOUnsafe getCurrentTime
-     let dt = queueLocalTimeInterval q
-     if timestamp >= addUTCTime dt timestamp0
-       then do ---
-               --- logDIO DEBUG $ "t = " ++ (show $ pointTime p) ++ ": updating the local time"
-               ---
-               liftIOUnsafe $
-                 do t <- readIORef (queueTime q)
-                    loct0 <- readIORef (queueLocalTime0 q)
-                    writeIORef (queueLocalTime q) (min t loct0)
-                    writeIORef (queueLocalTime0 q) t
-                    writeIORef (queueLocalTimeTimestamp q) timestamp
-                    return (t /= loct0)
-       else return False
-
--- | Get the local time.
-getLocalTime :: Event DIO Double
-getLocalTime =
-  Event $ \p ->
-  let q = runEventQueue $ pointRun p
-  in liftIOUnsafe $ readIORef (queueLocalTime q)
-
--- | Send the local time to the time server.
-sendLocalTime :: Event DIO ()
-sendLocalTime =
-  Event $ \p ->
-  do ---
-     --- invokeEvent p logSendLocalTime
-     ---
-     invokeEvent p updateLocalTime
-     t <- invokeEvent p getLocalTime
-     sender   <- messageInboxId
-     receiver <- timeServerId
-     liftDistributedUnsafe $
-       DP.send receiver (LocalTimeMessage sender t)
-
 -- | Synchronize the local time executing the specified computation.
 syncLocalTime :: Dynamics DIO () -> TimeWarp DIO ()
 syncLocalTime m =
@@ -587,11 +589,8 @@
                                 Just _  ->
                                   invokeTimeWarp p $ syncLocalTime m
                                 Nothing ->
-                                  do f <- invokeEvent p updateLocalTime
-                                     invokeEvent p sendLocalTime
-                                     if f
-                                       then invokeTimeWarp p $ syncLocalTime m
-                                       else invokeTimeWarp p $ syncLocalTime0 m
+                                  do invokeEvent p requestGlobalTime
+                                     invokeTimeWarp p $ syncLocalTime0 m
                       else return ()
   
 -- | Synchronize the local time executing the specified computation in ring 0.
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/Message.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/Message.hs
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/Message.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/Message.hs
@@ -15,6 +15,8 @@
        (Message(..),
         antiMessage,
         antiMessages,
+        AcknowledgmentMessage(..),
+        acknowledgmentMessage,
         LocalProcessMessage(..),
         TimeServerMessage(..)) where
 
@@ -70,15 +72,51 @@
     (messageReceiverId x == messageReceiverId y) &&
     (messageAntiToggle x == messageAntiToggle y)
 
+-- | Represents an acknowledgement message.
+data AcknowledgmentMessage =
+  AcknowledgmentMessage { acknowledgmentSequenceNo :: Int,
+                          -- ^ The sequence number.
+                          acknowledgmentSendTime :: Double,
+                          -- ^ The send time.
+                          acknowledgmentReceiveTime :: Double,
+                          -- ^ The receive time.
+                          acknowledgmentSenderId :: DP.ProcessId,
+                          -- ^ The sender of the source message.
+                          acknowledgmentReceiverId :: DP.ProcessId,
+                          -- ^ The receiver of the source message.
+                          acknowledgmentAntiToggle :: Bool,
+                          -- ^ Whether this is an anti-message acknowledgment.
+                          acknowledgmentMarked :: Bool
+                          -- ^ Whether the acknowledgment is marked.
+                        } deriving (Eq, Ord, Show, Typeable, Generic)
+
+instance Binary AcknowledgmentMessage
+
+-- | Create an acknowledgment message specifying whether it will be marked.
+acknowledgmentMessage :: Bool -> Message -> AcknowledgmentMessage
+acknowledgmentMessage marked x =
+  AcknowledgmentMessage { acknowledgmentSequenceNo = messageSequenceNo x,
+                          acknowledgmentSendTime = messageSendTime x,
+                          acknowledgmentReceiveTime = messageReceiveTime x,
+                          acknowledgmentSenderId = messageSenderId x,
+                          acknowledgmentReceiverId = messageReceiverId x,
+                          acknowledgmentAntiToggle = messageAntiToggle x,
+                          acknowledgmentMarked = marked
+                        }
+
 -- | The message sent to the local process.
 data LocalProcessMessage = QueueMessage Message
                            -- ^ the message has come from the remote process
                          | QueueMessageBulk [Message]
                            -- ^ a bulk of messages that have come from the remote process
-                         | GlobalTimeMessage (Maybe Double)
+                         | AcknowledgmentQueueMessage AcknowledgmentMessage
+                           -- ^ the acknowledgment message has come from the remote process
+                         | AcknowledgmentQueueMessageBulk [AcknowledgmentMessage]
+                           -- ^ a bulk of acknowledgment messages that have come from the remote process
+                         | ComputeLocalTimeMessage
+                           -- ^ the time server requests for a local minimum time
+                         | GlobalTimeMessage Double
                            -- ^ the time server sent a global time
-                         | LocalTimeMessageResp Double
-                           -- ^ the time server replied to 'LocalTimeMessage' sending its global time in response
                          | TerminateLocalProcessMessage
                            -- ^ the time server asked to terminate the process
                          deriving (Eq, Show, Typeable, Generic)
@@ -90,10 +128,10 @@
                          -- ^ register the local process in the time server
                        | UnregisterLocalProcessMessage DP.ProcessId
                          -- ^ unregister the local process from the time server
-                       | GlobalTimeMessageResp DP.ProcessId Double
-                         -- ^ the local process replied to 'GlobalTimeMessage' sending its local time in response
+                       | RequestGlobalTimeMessage DP.ProcessId
+                         -- ^ the local process requested for the global minimum time
                        | LocalTimeMessage DP.ProcessId Double
-                         -- ^ the local process sent its local time
+                         -- ^ the local process sent its local minimum time
                        | TerminateTimeServerMessage DP.ProcessId
                          -- ^ the local process asked to terminate the time server
                        deriving (Eq, Show, Typeable, Generic)
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs
@@ -38,18 +38,21 @@
 
 -- | Specifies the output message queue.
 data OutputMessageQueue =
-  OutputMessageQueue { outputMessages :: DLL.DoubleLinkedList Message,
+  OutputMessageQueue { outputEnqueueTransientMessage :: Message -> IO (),
+                       -- ^ Enqueue the transient message.
+                       outputMessages :: DLL.DoubleLinkedList Message,
                        -- ^ The output messages.
                        outputMessageSequenceNo :: IORef Int
                        -- ^ The next sequence number.
                      }
 
 -- | Create a new output message queue.
-newOutputMessageQueue :: DIO OutputMessageQueue
-newOutputMessageQueue =
+newOutputMessageQueue :: (Message -> IO ()) -> DIO OutputMessageQueue
+newOutputMessageQueue transient =
   do ms <- liftIOUnsafe DLL.newList
      rn <- liftIOUnsafe $ newIORef 0
-     return OutputMessageQueue { outputMessages = ms,
+     return OutputMessageQueue { outputEnqueueTransientMessage = transient,
+                                 outputMessages = ms,
                                  outputMessageSequenceNo = rn }
 
 -- | Return the output message queue size.
@@ -68,6 +71,7 @@
        do m' <- liftIOUnsafe $ DLL.listLast (outputMessages q)
           when (messageSendTime m' > messageSendTime m) $
             error "A new output message comes from the past: sendMessage."
+     liftIOUnsafe $ outputEnqueueTransientMessage q m
      deliverMessage m
      liftIOUnsafe $ DLL.listAddLast (outputMessages q) m
 
@@ -75,8 +79,11 @@
 rollbackOutputMessages :: OutputMessageQueue -> Double -> Bool -> DIO ()
 rollbackOutputMessages q t including =
   do ms <- liftIOUnsafe $ extractMessagesToRollback q t including
-     deliverAntiMessages $ map antiMessage ms
-     -- forM_ ms $ deliverAntiMessage . antiMessage
+     let ms' = map antiMessage ms
+     liftIOUnsafe $
+       forM_ ms' $ outputEnqueueTransientMessage q
+     deliverAntiMessages ms'
+     -- forM_ ms' deliverAntiMessage
                  
 -- | Return the messages to roolback by the specified time.
 extractMessagesToRollback :: OutputMessageQueue -> Double -> Bool -> IO [Message]
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs-boot b/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs-boot
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs-boot
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/OutputMessageQueue.hs-boot
@@ -26,7 +26,7 @@
 
 data OutputMessageQueue
 
-newOutputMessageQueue :: DIO OutputMessageQueue
+newOutputMessageQueue :: (Message -> IO ()) -> DIO OutputMessageQueue
 
 outputMessageQueueSize :: OutputMessageQueue -> IO Int
 
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/TimeServer.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/TimeServer.hs
--- a/Simulation/Aivika/Distributed/Optimistic/Internal/TimeServer.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/TimeServer.hs
@@ -14,13 +14,16 @@
 module Simulation.Aivika.Distributed.Optimistic.Internal.TimeServer
        (TimeServerParams(..),
         defaultTimeServerParams,
-        timeServer) where
+        timeServer,
+        curryTimeServer) where
 
 import qualified Data.Map as M
+import qualified Data.Set as S
 import Data.Maybe
 import Data.IORef
 import Data.Typeable
 import Data.Binary
+import Data.Time.Clock
 
 import GHC.Generics
 
@@ -28,7 +31,6 @@
 import Control.Monad.Trans
 import Control.Concurrent
 import qualified Control.Distributed.Process as DP
-import Control.Distributed.Process.Closure (remotable, mkClosure)
 
 import Simulation.Aivika.Distributed.Optimistic.Internal.Priority
 import Simulation.Aivika.Distributed.Optimistic.Internal.Message
@@ -40,7 +42,7 @@
                      tsExpectTimeout :: Int,
                      -- ^ the timeout in microseconds within which a new message is expected
                      tsTimeSyncDelay :: Int
-                     -- ^ the further delay in microseconds before the time synchronization
+                     -- ^ the delay in microseconds between the time synchronization sessions
                    } deriving (Eq, Ord, Show, Typeable, Generic)
 
 instance Binary TimeServerParams
@@ -49,51 +51,63 @@
 data TimeServer =
   TimeServer { tsParams :: TimeServerParams,
                -- ^ the time server parameters
+               tsInitQuorum :: Int,
+               -- ^ the initial quorum of registered local processes to start the simulation
+               tsInInit :: IORef Bool,
+               -- ^ whether the time server is in the initial mode
                tsProcesses :: IORef (M.Map DP.ProcessId LocalProcessInfo),
                -- ^ the information about local processes
-               tsGlobalTime :: IORef (Maybe Double),
+               tsProcessesInFind :: IORef (S.Set DP.ProcessId),
+               -- ^ the processed used in the current finding of the global time
+               tsGlobalTime :: IORef (Maybe Double)
                -- ^ the global time of the model
-               tsGlobalTimeInvalid :: IORef Bool
-               -- ^ whether the global time is invalid
              }
 
 -- | The information about the local process.
 data LocalProcessInfo =
-  LocalProcessInfo { lpLocalTime :: IORef (Maybe Double),
+  LocalProcessInfo { lpLocalTime :: IORef (Maybe Double)
                      -- ^ the local time of the process
-                     lpSentGlobalTime :: IORef (Maybe Double)
-                     -- ^ the global time sent to the process for the last time
                    }
 
 -- | The default time server parameters.
 defaultTimeServerParams :: TimeServerParams
 defaultTimeServerParams =
   TimeServerParams { tsLoggingPriority = WARNING,
-                     tsExpectTimeout = 1000,
-                     tsTimeSyncDelay = 1000
+                     tsExpectTimeout = 100000,
+                     tsTimeSyncDelay = 1000000
                    }
 
--- | Create a new time server.
-newTimeServer :: TimeServerParams -> IO TimeServer
-newTimeServer ps =
-  do m  <- newIORef M.empty
+-- | Create a new time server by the specified initial quorum and parameters.
+newTimeServer :: Int -> TimeServerParams -> IO TimeServer
+newTimeServer n ps =
+  do f  <- newIORef True
+     m  <- newIORef M.empty
+     s  <- newIORef S.empty
      t0 <- newIORef Nothing
-     f  <- newIORef False
      return TimeServer { tsParams = ps,
+                         tsInitQuorum = n,
+                         tsInInit = f,
                          tsProcesses = m,
-                         tsGlobalTime = t0,
-                         tsGlobalTimeInvalid = f
+                         tsProcessesInFind = s,
+                         tsGlobalTime = t0
                        }
 
 -- | Process the time server message.
 processTimeServerMessage :: TimeServer -> TimeServerMessage -> DP.Process ()
 processTimeServerMessage server (RegisterLocalProcessMessage pid) =
-  liftIO $
-  do t1 <- newIORef Nothing
-     t2 <- newIORef Nothing
-     writeIORef (tsGlobalTimeInvalid server) True
-     modifyIORef (tsProcesses server) $
-       M.insert pid LocalProcessInfo { lpLocalTime = t1, lpSentGlobalTime = t2 }
+  join $ liftIO $
+  do m <- readIORef (tsProcesses server)
+     case M.lookup pid m of
+       Just x ->
+         return $
+         logTimeServer server WARNING $
+         "Time Server: already registered process identifier " ++ show pid
+       Nothing  ->
+         do t <- newIORef Nothing
+            modifyIORef (tsProcesses server) $
+              M.insert pid LocalProcessInfo { lpLocalTime = t }
+            return $
+              tryStartTimeServer server
 processTimeServerMessage server (UnregisterLocalProcessMessage pid) =
   join $ liftIO $
   do m <- readIORef (tsProcesses server)
@@ -103,43 +117,26 @@
          logTimeServer server WARNING $
          "Time Server: unknown process identifier " ++ show pid
        Just x  ->
-         do t0 <- readIORef (tsGlobalTime server) 
-            t  <- readIORef (lpLocalTime x)
-            when (t0 .>=. t) $
-              writeIORef (tsGlobalTimeInvalid server) True
-            writeIORef (tsProcesses server) $
-              M.delete pid m
-            return $ return ()
+         do modifyIORef (tsProcesses server) $
+              M.delete pid
+            modifyIORef (tsProcessesInFind server) $
+              S.delete pid
+            return $
+              tryProvideTimeServerGlobalTime server
 processTimeServerMessage server (TerminateTimeServerMessage pid) =
   do pids <-
        liftIO $
        do m <- readIORef (tsProcesses server)
           writeIORef (tsProcesses server) M.empty
+          writeIORef (tsProcessesInFind server) S.empty
           writeIORef (tsGlobalTime server) Nothing
-          writeIORef (tsGlobalTimeInvalid server) True
           return $ filter (/= pid) (M.keys m)
      forM_ pids $ \pid ->
        DP.send pid TerminateLocalProcessMessage
      logTimeServer server INFO "Time Server: terminating..."
      DP.terminate
-processTimeServerMessage server (GlobalTimeMessageResp pid t') =
-  join $ liftIO $
-  do m <- readIORef (tsProcesses server)
-     case M.lookup pid m of
-       Nothing ->
-         return $
-         do logTimeServer server WARNING $
-              "Time Server: unknown process identifier " ++ show pid
-            processTimeServerMessage server (RegisterLocalProcessMessage pid)
-            processTimeServerMessage server (GlobalTimeMessageResp pid t')
-       Just x  ->
-         do t0 <- readIORef (tsGlobalTime server)
-            t  <- readIORef (lpLocalTime x)
-            when (t /= Just t') $
-              do writeIORef (lpLocalTime x) (Just t')
-                 when ((t0 .>=. t) || (t0 .>=. Just t')) $
-                   writeIORef (tsGlobalTimeInvalid server) True
-            return $ return ()
+processTimeServerMessage server (RequestGlobalTimeMessage pid) =
+  tryComputeTimeServerGlobalTime server
 processTimeServerMessage server (LocalTimeMessage pid t') =
   join $ liftIO $
   do m <- readIORef (tsProcesses server)
@@ -151,19 +148,11 @@
             processTimeServerMessage server (RegisterLocalProcessMessage pid)
             processTimeServerMessage server (LocalTimeMessage pid t')
        Just x  ->
-         do t0 <- readIORef (tsGlobalTime server)
-            t  <- readIORef (lpLocalTime x)
-            if t == Just t'
-              then return $ return ()
-              else do writeIORef (lpLocalTime x) (Just t')
-                      when ((t0 .>=. t) || (t0 .>=. Just t')) $
-                        writeIORef (tsGlobalTimeInvalid server) True
-                      t0' <- readIORef (lpSentGlobalTime x)
-                      if (t0 == t0') || (isNothing t0)
-                        then return $ return ()
-                        else do writeIORef (lpSentGlobalTime x) t0
-                                return $
-                                  DP.send pid (LocalTimeMessageResp $ fromJust t0)
+         do writeIORef (lpLocalTime x) (Just t')
+            modifyIORef (tsProcessesInFind server) $
+              S.delete pid
+            return $
+              tryProvideTimeServerGlobalTime server
 
 -- | Whether the both values are defined and the first is greater than or equaled to the second.
 (.>=.) :: Maybe Double -> Maybe Double -> Bool
@@ -175,68 +164,136 @@
 (.>.) (Just x) (Just y) = x > y
 (.>.) _ _ = False
 
--- | Validate the time server.
-validateTimeServer :: TimeServer -> DP.Process ()
-validateTimeServer server =
-  do f <- liftIO $ readIORef (tsGlobalTimeInvalid server)
-     when f $
-       do t0 <- timeServerGlobalTime server
-          case t0 of
-            Nothing -> return ()
-            Just t0 ->
-              do t' <- liftIO $ readIORef (tsGlobalTime server)
-                 when (t' .>. Just t0) $
-                   logTimeServer server NOTICE
-                   "Time Server: the global time has decreased"
-                 liftIO $
-                   do writeIORef (tsGlobalTime server) (Just t0)
-                      writeIORef (tsGlobalTimeInvalid server) False
-                 m <- liftIO $ readIORef (tsProcesses server)
-                 forM_ (M.assocs m) $ \(pid, x) ->
-                   do t0' <- liftIO $ readIORef (lpSentGlobalTime x)
-                      when (t0' /= Just t0) $
-                        do liftIO $ writeIORef (lpSentGlobalTime x) (Just t0)
-                           DP.send pid (GlobalTimeMessage $ Just t0) 
+-- | Try to start synchronizing the global time.
+tryStartTimeServer :: TimeServer -> DP.Process ()
+tryStartTimeServer server =
+  join $ liftIO $
+  do f <- readIORef (tsInInit server)
+     if not f
+       then return $
+            return ()
+       else do m <- readIORef (tsProcesses server)
+               if M.size m < tsInitQuorum server
+                 then return $
+                      return ()
+                 else do writeIORef (tsInInit server) False
+                         return $
+                           do logTimeServer server INFO $
+                                "Time Server: starting"
+                              tryComputeTimeServerGlobalTime server
+  
+-- | Try to compute the global time and provide the local processes with it.
+tryComputeTimeServerGlobalTime :: TimeServer -> DP.Process ()
+tryComputeTimeServerGlobalTime server =
+  join $ liftIO $
+  do f <- readIORef (tsInInit server)
+     if f
+       then return $
+            return ()
+       else do s <- readIORef (tsProcessesInFind server)
+               if S.size s > 0
+                 then return $
+                      return ()
+                 else return $
+                      computeTimeServerGlobalTime server
 
+-- | Try to provide the local processes wth the global time. 
+tryProvideTimeServerGlobalTime :: TimeServer -> DP.Process ()
+tryProvideTimeServerGlobalTime server =
+  join $ liftIO $
+  do f <- readIORef (tsInInit server)
+     if f
+       then return $
+            return ()
+       else do s <- readIORef (tsProcessesInFind server)
+               if S.size s > 0
+                 then return $
+                      return ()
+                 else return $
+                      provideTimeServerGlobalTime server
+
+-- | Initiate computing the global time.
+computeTimeServerGlobalTime :: TimeServer -> DP.Process ()
+computeTimeServerGlobalTime server =
+  do logTimeServer server DEBUG $
+       "Time Server: computing the global time..."
+     zs <- liftIO $ fmap M.assocs $ readIORef (tsProcesses server)
+     forM_ zs $ \(pid, x) ->
+       liftIO $
+       modifyIORef (tsProcessesInFind server) $
+       S.insert pid
+     forM_ zs $ \(pid, x) ->
+       DP.send pid ComputeLocalTimeMessage
+
+-- | Provide the local processes with the global time.
+provideTimeServerGlobalTime :: TimeServer -> DP.Process ()
+provideTimeServerGlobalTime server =
+  do t0 <- liftIO $ timeServerGlobalTime server
+     logTimeServer server DEBUG $
+       "Time Server: providing the global time = " ++ show t0
+     case t0 of
+       Nothing -> return ()
+       Just t0 ->
+         do t' <- liftIO $ readIORef (tsGlobalTime server)
+            when (t' .>. Just t0) $
+              logTimeServer server NOTICE
+              "Time Server: the global time has decreased"
+            liftIO $ writeIORef (tsGlobalTime server) (Just t0)
+            zs <- liftIO $ fmap M.assocs $ readIORef (tsProcesses server)
+            forM_ zs $ \(pid, x) ->
+              DP.send pid (GlobalTimeMessage t0)
+
 -- | Return the time server global time.
-timeServerGlobalTime :: TimeServer -> DP.Process (Maybe Double)
+timeServerGlobalTime :: TimeServer -> IO (Maybe Double)
 timeServerGlobalTime server =
-  do t0 <- liftIO $ readIORef (tsGlobalTime server)
-     zs <- liftIO $ fmap M.assocs $ readIORef (tsProcesses server)
+  do zs <- fmap M.assocs $ readIORef (tsProcesses server)
      case zs of
        [] -> return Nothing
        ((pid, x) : zs') ->
-         do t <- liftIO $ readIORef (lpLocalTime x)
+         do t <- readIORef (lpLocalTime x)
             loop zs t
               where loop [] acc = return acc
                     loop ((pid, x) : zs') acc =
-                      do t <- liftIO $ readIORef (lpLocalTime x)
+                      do t <- readIORef (lpLocalTime x)
                          case t of
                            Nothing ->
-                             do DP.send pid (GlobalTimeMessage Nothing)
-                                loop zs' Nothing
+                             loop zs' Nothing
                            Just _  ->
                              loop zs' (liftM2 min t acc)
 
--- | Start the time server.
-timeServer :: TimeServerParams -> DP.Process ()
-timeServer ps =
-  do server <- liftIO $ newTimeServer ps
+-- | Convert seconds to microseconds.
+secondsToMicroseconds :: Double -> Int
+secondsToMicroseconds x = fromInteger $ toInteger $ round (1000000 * x)
+
+-- | Start the time server by the specified initial quorum and parameters.
+-- The quorum defines the number of local processes that must be registered in
+-- the time server before the global time synchronization is started.
+timeServer :: Int -> TimeServerParams -> DP.Process ()
+timeServer n ps =
+  do server <- liftIO $ newTimeServer n ps
      logTimeServer server INFO "Time Server: starting..."
-     forever $
-       do m <- DP.expectTimeout (tsExpectTimeout ps) :: DP.Process (Maybe TimeServerMessage)
-          case m of
-            Nothing -> return ()
-            Just m  ->
-              do ---
-                 logTimeServer server DEBUG $
-                   "Time Server: " ++ show m
-                 ---
-                 processTimeServerMessage server m
-          liftIO $
-            threadDelay (tsTimeSyncDelay ps)
-          validateTimeServer server
+     let loop utc0 =
+           do m <- DP.expectTimeout (tsExpectTimeout ps) :: DP.Process (Maybe TimeServerMessage)
+              case m of
+                Nothing -> return ()
+                Just m  ->
+                  do ---
+                     logTimeServer server DEBUG $
+                       "Time Server: " ++ show m
+                     ---
+                     processTimeServerMessage server m
+              utc <- liftIO getCurrentTime
+              let dt = fromRational $ toRational (diffUTCTime utc utc0)
+              if secondsToMicroseconds dt > tsTimeSyncDelay ps
+                then do tryComputeTimeServerGlobalTime server
+                        loop utc
+                else loop utc0
+     liftIO getCurrentTime >>= loop 
 
+-- | A curried version of 'timeServer' for starting the time server on remote node.
+curryTimeServer :: (Int, TimeServerParams) -> DP.Process ()
+curryTimeServer (n, ps) = timeServer n ps
+
 -- | Log the message with the specified priority.
 logTimeServer :: TimeServer -> Priority -> String -> DP.Process ()
 {-# INLINE logTimeServer #-}
@@ -244,4 +301,3 @@
   when (tsLoggingPriority (tsParams server) <= p) $
   DP.say $
   embracePriority p ++ " " ++ message
-
diff --git a/Simulation/Aivika/Distributed/Optimistic/Internal/TransientMessageQueue.hs b/Simulation/Aivika/Distributed/Optimistic/Internal/TransientMessageQueue.hs
new file mode 100644
--- /dev/null
+++ b/Simulation/Aivika/Distributed/Optimistic/Internal/TransientMessageQueue.hs
@@ -0,0 +1,163 @@
+
+-- |
+-- Module     : Simulation.Aivika.Distributed.Optimistic.Internal.TransientMessageQueue
+-- Copyright  : Copyright (c) 2015-2016, David Sorokin <david.sorokin@gmail.com>
+-- License    : BSD3
+-- Maintainer : David Sorokin <david.sorokin@gmail.com>
+-- Stability  : experimental
+-- Tested with: GHC 8.0.1
+--
+-- This module defines a transient message queue.
+--
+module Simulation.Aivika.Distributed.Optimistic.Internal.TransientMessageQueue
+       (TransientMessageQueue,
+        newTransientMessageQueue,
+        transientMessageQueueSize,
+        transientMessageQueueTime,
+        enqueueTransientMessage,
+        processAcknowledgmentMessage,
+        acknowledgmentMessageTime,
+        resetAcknowledgmentMessageTime,
+        deliverAcknowledgmentMessage,
+        deliverAcknowledgmentMessages) where
+
+import qualified Data.Set as S
+import Data.List
+import Data.IORef
+
+import Control.Monad
+import Control.Monad.Trans
+import qualified Control.Distributed.Process as DP
+
+import Simulation.Aivika.Distributed.Optimistic.Internal.Message
+import Simulation.Aivika.Distributed.Optimistic.Internal.DIO
+import Simulation.Aivika.Distributed.Optimistic.Internal.IO
+
+-- | Specifies the transient message queue.
+data TransientMessageQueue =
+  TransientMessageQueue { queuePrototypeMessages :: IORef (S.Set TransientMessageQueueItem),
+                          -- ^ The prototype messages.
+                          queueMarkedMessageTime :: IORef Double
+                          -- ^ The marked acknowledgment message time.
+                        }
+
+-- | Represents an acknowledgement message representative.
+data TransientMessageQueueItem =
+  TransientMessageQueueItem { itemSequenceNo :: Int,
+                              -- ^ The sequence number.
+                              itemSendTime :: Double,
+                              -- ^ The send time.
+                              itemReceiveTime :: Double,
+                              -- ^ The receive time.
+                              itemSenderId :: DP.ProcessId,
+                              -- ^ The sender of the source message.
+                              itemReceiverId :: DP.ProcessId,
+                              -- ^ The receiver of the source message.
+                              itemAntiToggle :: Bool
+                              -- ^ Whether it was the anti-message acknowledgment.
+                            } deriving (Eq, Show)
+
+instance Ord TransientMessageQueueItem where
+
+  x <= y
+    | (itemReceiveTime x < itemReceiveTime y) = True
+    | (itemReceiveTime x > itemReceiveTime y) = False
+    | (itemSendTime x < itemSendTime y)       = True
+    | (itemSendTime x > itemSendTime y)       = False
+    | (itemSequenceNo x < itemSequenceNo y)   = True
+    | (itemSequenceNo x > itemSequenceNo y)   = False
+    | (itemReceiverId x < itemReceiverId y)   = True
+    | (itemReceiverId x > itemReceiverId y)   = False
+    | (itemSenderId x < itemSenderId y)       = True
+    | (itemSenderId x > itemSenderId y)       = False
+    | (itemAntiToggle x < itemAntiToggle y)   = True
+    | (itemAntiToggle x > itemAntiToggle y)   = False
+    | otherwise                               = True
+
+-- | Return a queue item by the specified transient message.
+transientMessageQueueItem :: Message -> TransientMessageQueueItem
+transientMessageQueueItem m =
+  TransientMessageQueueItem { itemSequenceNo  = messageSequenceNo m,
+                              itemSendTime    = messageSendTime m,
+                              itemReceiveTime = messageReceiveTime m,
+                              itemSenderId    = messageSenderId m,
+                              itemReceiverId  = messageReceiverId m,
+                              itemAntiToggle  = messageAntiToggle m }
+
+-- | Return a queue item by the specified acknowledgment message.
+acknowledgmentMessageQueueItem :: AcknowledgmentMessage -> TransientMessageQueueItem
+acknowledgmentMessageQueueItem m =
+  TransientMessageQueueItem { itemSequenceNo  = acknowledgmentSequenceNo m,
+                              itemSendTime    = acknowledgmentSendTime m,
+                              itemReceiveTime = acknowledgmentReceiveTime m,
+                              itemSenderId    = acknowledgmentSenderId m,
+                              itemReceiverId  = acknowledgmentReceiverId m,
+                              itemAntiToggle  = acknowledgmentAntiToggle m }
+
+-- | Create a new transient message queue.
+newTransientMessageQueue :: DIO TransientMessageQueue
+newTransientMessageQueue =
+  do ms <- liftIOUnsafe $ newIORef S.empty
+     r  <- liftIOUnsafe $ newIORef (1 / 0)
+     return TransientMessageQueue { queuePrototypeMessages = ms,
+                                    queueMarkedMessageTime = r }
+
+-- | Get the transient message queue size.
+transientMessageQueueSize :: TransientMessageQueue -> IO Int
+transientMessageQueueSize q =
+  fmap S.size $ readIORef (queuePrototypeMessages q)
+
+-- | Get the virtual time of the transient message queue.
+transientMessageQueueTime :: TransientMessageQueue -> IO Double
+transientMessageQueueTime q =
+  do s <- readIORef (queuePrototypeMessages q)
+     if S.null s
+       then return (1 / 0)
+       else let m = S.findMin s
+            in return (itemReceiveTime m)
+
+-- | Enqueue the transient message.
+enqueueTransientMessage :: TransientMessageQueue -> Message -> IO ()
+enqueueTransientMessage q m =
+  modifyIORef (queuePrototypeMessages q) $
+  S.insert (transientMessageQueueItem m)
+
+-- | Enqueue the acknowledgment message.
+enqueueAcknowledgmentMessage :: TransientMessageQueue -> AcknowledgmentMessage -> IO ()
+enqueueAcknowledgmentMessage q m =
+  modifyIORef' (queueMarkedMessageTime q) $
+  min (acknowledgmentReceiveTime m)
+
+-- | Process the acknowledgment message.
+processAcknowledgmentMessage :: TransientMessageQueue -> AcknowledgmentMessage -> IO () 
+processAcknowledgmentMessage q m =
+  do modifyIORef (queuePrototypeMessages q) $
+       S.delete (acknowledgmentMessageQueueItem m)
+     when (acknowledgmentMarked m) $
+       enqueueAcknowledgmentMessage q m
+
+-- | Get the minimal marked acknowledgment message time.
+acknowledgmentMessageTime :: TransientMessageQueue -> IO Double
+acknowledgmentMessageTime q =
+  readIORef (queueMarkedMessageTime q)
+
+-- | Reset the marked acknowledgment message time.
+resetAcknowledgmentMessageTime :: TransientMessageQueue -> IO ()
+resetAcknowledgmentMessageTime q =
+  writeIORef (queueMarkedMessageTime q) (1 / 0)
+
+-- | Deliver the acknowledgment message on low level.
+deliverAcknowledgmentMessage :: AcknowledgmentMessage -> DIO ()
+deliverAcknowledgmentMessage x =
+  liftDistributedUnsafe $
+  DP.send (acknowledgmentSenderId x) (AcknowledgmentQueueMessage x)
+
+-- | Deliver the acknowledgment messages on low level.
+deliverAcknowledgmentMessages :: [AcknowledgmentMessage] -> DIO ()
+deliverAcknowledgmentMessages xs =
+  let ys = groupBy (\a b -> acknowledgmentSenderId a == acknowledgmentSenderId b) xs
+      dlv []         = return ()
+      dlv zs@(z : _) =
+        liftDistributedUnsafe $
+        DP.send (acknowledgmentSenderId z) (AcknowledgmentQueueMessageBulk zs)
+  in forM_ ys dlv
diff --git a/Simulation/Aivika/Distributed/Optimistic/TimeServer.hs b/Simulation/Aivika/Distributed/Optimistic/TimeServer.hs
--- a/Simulation/Aivika/Distributed/Optimistic/TimeServer.hs
+++ b/Simulation/Aivika/Distributed/Optimistic/TimeServer.hs
@@ -12,6 +12,7 @@
 module Simulation.Aivika.Distributed.Optimistic.TimeServer
        (TimeServerParams(..),
         defaultTimeServerParams,
-        timeServer) where
+        timeServer,
+        curryTimeServer) where
 
 import Simulation.Aivika.Distributed.Optimistic.Internal.TimeServer
diff --git a/aivika-distributed.cabal b/aivika-distributed.cabal
--- a/aivika-distributed.cabal
+++ b/aivika-distributed.cabal
@@ -1,9 +1,10 @@
 name:            aivika-distributed
-version:         0.2
+version:         0.3
 synopsis:        Parallel distributed discrete event simulation module for the Aivika library
 description:
     This package extends the aivika-transformers [1] package with facilities for running parallel distributed simulations.
-    It uses an optimistic strategy known as the Time Warp method.
+    It uses an optimistic strategy known as the Time Warp method. To synchronize the global virtual time, since version 0.3
+    it uses Samadi's algorithm.
     .
     \[1] <http://hackage.haskell.org/package/aivika-transformers>
     .
@@ -25,6 +26,7 @@
                      tests/MachRep2Reproducible.hs
                      tests/MachRep2Sync.hs
                      tests/MachRep2SyncIO.hs
+                     CHANGELOG.md
 
 library
 
@@ -49,6 +51,7 @@
                      Simulation.Aivika.Distributed.Optimistic.Internal.Ref
                      Simulation.Aivika.Distributed.Optimistic.Internal.TimeServer
                      Simulation.Aivika.Distributed.Optimistic.Internal.TimeWarp
+                     Simulation.Aivika.Distributed.Optimistic.Internal.TransientMessageQueue
                      Simulation.Aivika.Distributed.Optimistic.Internal.UndoableLog
 
     build-depends:   base >= 3 && < 6,
diff --git a/tests/MachRep1.hs b/tests/MachRep1.hs
--- a/tests/MachRep1.hs
+++ b/tests/MachRep1.hs
@@ -104,7 +104,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = NOTICE }
-    m  = do runSimulation (slaveModel masterId) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId) specs
             unregisterDIO
 
 runMasterModel :: DP.ProcessId -> Int -> DP.Process (DP.ProcessId, DP.Process Double)
@@ -112,14 +113,15 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = NOTICE }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
 master = \backend nodes ->
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId <- DP.spawnLocal $ timeServer 3 timeServerParams
      (masterId, masterProcess) <- runMasterModel timeServerId 2
      forM_ [1..2] $ \i ->
        do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId)
diff --git a/tests/MachRep1Simple.hs b/tests/MachRep1Simple.hs
--- a/tests/MachRep1Simple.hs
+++ b/tests/MachRep1Simple.hs
@@ -71,7 +71,8 @@
   do DP.say "Started simulating..."
      let ps = defaultDIOParams { dioLoggingPriority = NOTICE }
          m =
-           do a <- runSimulation model specs
+           do registerDIO
+              a <- runSimulation model specs
               terminateDIO
               return a
      (modelId, modelProcess) <- runDIO m ps timeServerId
@@ -81,7 +82,7 @@
 master = \backend nodes ->
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId  <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId  <- DP.spawnLocal $ timeServer 1 timeServerParams
      runModel timeServerId
      liftIO $
        threadDelay 1000000
diff --git a/tests/MachRep2.hs b/tests/MachRep2.hs
--- a/tests/MachRep2.hs
+++ b/tests/MachRep2.hs
@@ -197,7 +197,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do runSimulation (slaveModel masterId) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId) specs
             unregisterDIO
 
 runMasterModel :: DP.ProcessId -> Int -> DP.Process (DP.ProcessId, DP.Process (Double, Double))
@@ -205,7 +206,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
@@ -213,7 +215,7 @@
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let n = 2
          timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId <- DP.spawnLocal $ timeServer 3 timeServerParams
      (masterId, masterProcess) <- runMasterModel timeServerId n
      forM_ [1..n] $ \i ->
        do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId)
diff --git a/tests/MachRep2Distributed.hs b/tests/MachRep2Distributed.hs
--- a/tests/MachRep2Distributed.hs
+++ b/tests/MachRep2Distributed.hs
@@ -216,7 +216,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do runSimulation (slaveModel masterId) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId) specs
             unregisterDIO
 
 startSlaveModel :: (DP.ProcessId, DP.ProcessId) -> DP.Process ()
@@ -224,14 +225,15 @@
   do (slaveId, slaveProcess) <- runSlaveModel x
      slaveProcess
 
-remotable ['startSlaveModel, 'timeServer]
+remotable ['startSlaveModel, 'curryTimeServer]
 
 runMasterModel :: DP.ProcessId -> Int -> DP.Process (DP.ProcessId, DP.Process (Double, Double))
 runMasterModel timeServerId n =
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
@@ -240,7 +242,7 @@
      let [n0, n1, n2] = nodes
          timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
      -- timeServerId <- DP.spawnLocal $ timeServer timeServerParams
-     timeServerId <- DP.spawn n0 ($(mkClosure 'timeServer) timeServerParams)
+     timeServerId <- DP.spawn n0 ($(mkClosure 'curryTimeServer) (3 :: Int, timeServerParams))
      -- (masterId, masterProcess) <- runMasterModel timeServerId 2
      -- forM_ [1..2] $ \i ->
      --   do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId)
diff --git a/tests/MachRep2Reproducible.hs b/tests/MachRep2Reproducible.hs
--- a/tests/MachRep2Reproducible.hs
+++ b/tests/MachRep2Reproducible.hs
@@ -213,7 +213,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do runSimulation (slaveModel masterId i) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId i) specs
             unregisterDIO
 
 -- remotable ['runSlaveModel, 'timeServer]
@@ -223,7 +224,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
@@ -231,7 +233,7 @@
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let n = length seeds
          timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId <- DP.spawnLocal $ timeServer 3 timeServerParams
      (masterId, masterProcess) <- runMasterModel timeServerId n
      forM_ [1..n] $ \i ->
        do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId, i)
diff --git a/tests/MachRep2Sync.hs b/tests/MachRep2Sync.hs
--- a/tests/MachRep2Sync.hs
+++ b/tests/MachRep2Sync.hs
@@ -202,7 +202,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do runSimulation (slaveModel masterId) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId) specs
             unregisterDIO
 
 runMasterModel :: DP.ProcessId -> Int -> DP.Process (DP.ProcessId, DP.Process (Double, Double))
@@ -210,7 +211,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
@@ -218,7 +220,7 @@
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let n = 2
          timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId <- DP.spawnLocal $ timeServer 3 timeServerParams
      (masterId, masterProcess) <- runMasterModel timeServerId n
      forM_ [1..n] $ \i ->
        do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId)
diff --git a/tests/MachRep2SyncIO.hs b/tests/MachRep2SyncIO.hs
--- a/tests/MachRep2SyncIO.hs
+++ b/tests/MachRep2SyncIO.hs
@@ -204,7 +204,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do runSimulation (slaveModel masterId) specs
+    m  = do registerDIO
+            runSimulation (slaveModel masterId) specs
             unregisterDIO
 
 runMasterModel :: DP.ProcessId -> Int -> DP.Process (DP.ProcessId, DP.Process (Double, Double))
@@ -212,7 +213,8 @@
   runDIO m ps timeServerId
   where
     ps = defaultDIOParams { dioLoggingPriority = WARNING }
-    m  = do a <- runSimulation (masterModel n) specs
+    m  = do registerDIO
+            a <- runSimulation (masterModel n) specs
             terminateDIO
             return a
 
@@ -220,7 +222,7 @@
   do liftIO . putStrLn $ "Slaves: " ++ show nodes
      let n = 2
          timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
-     timeServerId <- DP.spawnLocal $ timeServer timeServerParams
+     timeServerId <- DP.spawnLocal $ timeServer 3 timeServerParams
      (masterId, masterProcess) <- runMasterModel timeServerId n
      forM_ [1..n] $ \i ->
        do (slaveId, slaveProcess) <- runSlaveModel (timeServerId, masterId)
