summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/Server.hs126
1 files changed, 46 insertions, 80 deletions
diff --git a/Presence/Server.hs b/Presence/Server.hs
index 14eab06c..ff3c5d42 100644
--- a/Presence/Server.hs
+++ b/Presence/Server.hs
@@ -378,7 +378,7 @@ server = do
378 expected = fromIntegral interval 378 expected = fromIntegral interval
379 when (retry && elapsed < expected) $ do 379 when (retry && elapsed < expected) $ do
380 debugNoise $ "Waiting to retry " <> bshow addr 380 debugNoise $ "Waiting to retry " <> bshow addr
381 startDelay timer (round $ 1000 * (expected-elapsed)) 381 void $ startDelay timer (round $ 1000 * (expected-elapsed))
382 debugNoise $ "retry " <> bshow (retry,addr) 382 debugNoise $ "retry " <> bshow (retry,addr)
383 when retry $ retryLoop 383 when retry $ retryLoop
384 384
@@ -750,96 +750,60 @@ debugNoise str = warn str -- return ()
750data PingEvent = PingIdle | PingTimeOut 750data PingEvent = PingIdle | PingTimeOut
751 751
752data PingMachine = PingMachine 752data PingMachine = PingMachine
753 { pingIdle :: PingInterval 753 { pingFlag :: TVar Bool
754 , pingTimeOut :: TimeOut 754 , pingInterruptable :: InterruptableDelay
755 , pingDelay :: TMVar (Int,PingEvent)
756 , pingEvent :: TMVar PingEvent 755 , pingEvent :: TMVar PingEvent
757 , pingStarted :: TMVar Bool -- True when a threadDelay is running 756 , pingStarted :: TMVar Bool
758 , pingThread :: ThreadId
759 , pingFlag :: TVar Bool
760 } 757 }
761 758
762pingMachine :: PingInterval -> TimeOut -> IO PingMachine 759pingMachine :: PingInterval -> TimeOut -> IO PingMachine
763pingMachine idle timeout = do 760pingMachine idle timeout = do
764 me <- do 761 d <- interruptableDelay
765 (delayVar,eventVar,startedVar,flag) <- atomically $ do 762 flag <- atomically $ newTVar False
766 d <- newEmptyTMVar 763 canceled <- atomically $ newTVar False
767 e <- newEmptyTMVar 764 event <- atomically newEmptyTMVar
768 s <- newTMVar False 765 started <- atomically $ newEmptyTMVar
769 f <- newTVar False 766 thread <- forkIO $ do
770 return (d,e,s,f) 767 (>>=) (atomically (readTMVar started)) $ flip when $ do
771 return PingMachine { pingIdle = idle 768 fix $ \loop -> do
772 , pingTimeOut = timeout 769 atomically $ writeTVar flag False
773 , pingDelay = delayVar 770 fin <- startDelay d (1000*idle)
774 , pingEvent = eventVar 771 (>>=) (atomically (readTMVar started)) $ flip when $ do
775 , pingStarted = startedVar 772 when (not fin) loop
776 , pingThread = undefined 773 -- Idle event
777 , pingFlag = flag } 774 atomically $ do
778 thread <- forkIO . when (pingIdle me /=0) . fix $ 775 tryTakeTMVar event
779 \loop -> do 776 putTMVar event PingIdle
780 (delay,event) <- atomically $ takeTMVar (pingDelay me) 777 writeTVar flag True
781 when (delay /= 0) $ do 778 fin <- startDelay d (1000*timeout)
782 handle (\(ErrorCall _)-> do 779 (>>=) (atomically (readTMVar started)) $ flip when $ do
783 atomically $ do takeTMVar (pingStarted me) 780 when (not fin) loop
784 putTMVar (pingStarted me) False 781 -- Timeout event
785 loop) 782 atomically $ do
786 (do atomically $ do takeTMVar (pingStarted me) 783 tryTakeTMVar event
787 putTMVar (pingStarted me) True 784 writeTVar flag False
788 threadDelay delay 785 putTMVar event PingTimeOut
789 atomically $ do takeTMVar (pingStarted me) 786 return PingMachine
790 putTMVar (pingStarted me) False 787 { pingFlag = flag
791 atomically $ putTMVar (pingEvent me) event 788 , pingInterruptable = d
792 case event of PingTimeOut -> return () 789 , pingEvent = event
793 PingIdle -> loop) 790 , pingStarted = started
794 791 }
795 return me { pingThread = thread }
796 792
797pingCancel :: PingMachine -> IO () 793pingCancel :: PingMachine -> IO ()
798pingCancel me = do 794pingCancel me = do
799 b <- atomically $ do 795 atomically $ do tryTakeTMVar (pingStarted me)
800 tryTakeTMVar (pingDelay me) -- no hang 796 putTMVar (pingStarted me) False
801 putTMVar (pingDelay me) (0,PingTimeOut) 797 interruptDelay (pingInterruptable me)
802 takeTMVar (pingStarted me)
803 when b $ throwTo (pingThread me) $ ErrorCall ""
804 atomically $ putTMVar (pingStarted me) b
805 798
806pingBump :: PingMachine -> IO () 799pingBump :: PingMachine -> IO ()
807pingBump me = do 800pingBump me = do
808 b <- atomically $ do 801 atomically $ do tryTakeTMVar (pingStarted me)
809 when (pingIdle me /= 0) $ do 802 putTMVar (pingStarted me) True
810 e <- tryReadTMVar (pingDelay me) 803 interruptDelay (pingInterruptable me)
811 case e of
812 Just (0,PingTimeOut) -> return () -- canceled/fired
813 Just _ -> retry
814 Nothing -> putTMVar (pingDelay me)
815 (1000*pingIdle me,PingIdle)
816 takeTMVar (pingStarted me)
817 when b $ throwTo (pingThread me) $ ErrorCall ""
818 {-
819 utc <- getCurrentTime
820 let utc' = formatTime defaultTimeLocale "%s" utc
821 warn $ "BUMP " <> bshow utc' <> " " <> bshow (pingIdle me, pingTimeOut me)
822 -}
823 atomically $ putTMVar (pingStarted me) b
824{-
825pingBump me = do
826 b <- atomically $ do
827 when (pingIdle me /= 0) $
828 putTMVar (pingDelay me) (1000*pingIdle me,PingIdle)
829 readTMVar (pingStarted me)
830 when b $ throwTo (pingThread me) $ ErrorCall ""
831-}
832 804
833pingWait :: PingMachine -> STM PingEvent 805pingWait :: PingMachine -> STM PingEvent
834pingWait me = do 806pingWait me = takeTMVar (pingEvent me)
835 e <- takeTMVar (pingEvent me)
836 case e of
837 PingIdle -> do writeTVar (pingFlag me) True
838 putTMVar (pingDelay me)
839 (1000*pingTimeOut me,PingTimeOut)
840 PingTimeOut -> putTMVar (pingDelay me)
841 (0,PingTimeOut)
842 return e
843 807
844 808
845data InterruptableDelay = InterruptableDelay 809data InterruptableDelay = InterruptableDelay
@@ -851,14 +815,16 @@ interruptableDelay = do
851 fmap InterruptableDelay 815 fmap InterruptableDelay
852 $ atomically newEmptyTMVar 816 $ atomically newEmptyTMVar
853 817
854startDelay :: InterruptableDelay -> Microseconds -> IO () 818startDelay :: InterruptableDelay -> Microseconds -> IO Bool
855startDelay d interval = do 819startDelay d interval = do
856 thread <- myThreadId 820 thread <- myThreadId
857 handle (\(ErrorCall _)-> do 821 handle (\(ErrorCall _)-> do
858 debugNoise $ "delay interrupted" ) $ do 822 debugNoise $ "delay interrupted"
823 return False) $ do
859 atomically $ putTMVar (delayThread d) thread 824 atomically $ putTMVar (delayThread d) thread
860 threadDelay interval 825 threadDelay interval
861 void . atomically $ takeTMVar (delayThread d) 826 void . atomically $ takeTMVar (delayThread d)
827 return True
862 828
863interruptDelay :: InterruptableDelay -> IO () 829interruptDelay :: InterruptableDelay -> IO ()
864interruptDelay d = do 830interruptDelay d = do