diff options
author | joe <joe@jerkface.net> | 2014-02-14 16:59:57 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-02-14 16:59:57 -0500 |
commit | dcf0f3e629a1d77c405f035c70548e6b9f873845 (patch) | |
tree | e4d734499b831bb73d453ef0ca9485a33a8f23d4 /Presence/Server.hs | |
parent | b4a27723cc386e3a397e6f8c8e32564ac57c4b0e (diff) |
Ping now uses InterruptableDelay
Diffstat (limited to 'Presence/Server.hs')
-rw-r--r-- | Presence/Server.hs | 126 |
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 () | |||
750 | data PingEvent = PingIdle | PingTimeOut | 750 | data PingEvent = PingIdle | PingTimeOut |
751 | 751 | ||
752 | data PingMachine = PingMachine | 752 | data 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 | ||
762 | pingMachine :: PingInterval -> TimeOut -> IO PingMachine | 759 | pingMachine :: PingInterval -> TimeOut -> IO PingMachine |
763 | pingMachine idle timeout = do | 760 | pingMachine 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 | ||
797 | pingCancel :: PingMachine -> IO () | 793 | pingCancel :: PingMachine -> IO () |
798 | pingCancel me = do | 794 | pingCancel 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 | ||
806 | pingBump :: PingMachine -> IO () | 799 | pingBump :: PingMachine -> IO () |
807 | pingBump me = do | 800 | pingBump 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 | {- | ||
825 | pingBump 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 | ||
833 | pingWait :: PingMachine -> STM PingEvent | 805 | pingWait :: PingMachine -> STM PingEvent |
834 | pingWait me = do | 806 | pingWait 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 | ||
845 | data InterruptableDelay = InterruptableDelay | 809 | data InterruptableDelay = InterruptableDelay |
@@ -851,14 +815,16 @@ interruptableDelay = do | |||
851 | fmap InterruptableDelay | 815 | fmap InterruptableDelay |
852 | $ atomically newEmptyTMVar | 816 | $ atomically newEmptyTMVar |
853 | 817 | ||
854 | startDelay :: InterruptableDelay -> Microseconds -> IO () | 818 | startDelay :: InterruptableDelay -> Microseconds -> IO Bool |
855 | startDelay d interval = do | 819 | startDelay 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 | ||
863 | interruptDelay :: InterruptableDelay -> IO () | 829 | interruptDelay :: InterruptableDelay -> IO () |
864 | interruptDelay d = do | 830 | interruptDelay d = do |