summaryrefslogtreecommitdiff
path: root/PingMachine.hs
diff options
context:
space:
mode:
Diffstat (limited to 'PingMachine.hs')
-rw-r--r--PingMachine.hs48
1 files changed, 48 insertions, 0 deletions
diff --git a/PingMachine.hs b/PingMachine.hs
index 5cd70f95..4a1cb008 100644
--- a/PingMachine.hs
+++ b/PingMachine.hs
@@ -1,6 +1,8 @@
1{-# LANGUAGE CPP #-} 1{-# LANGUAGE CPP #-}
2{-# LANGUAGE TupleSections #-}
2module PingMachine where 3module PingMachine where
3 4
5import Control.Applicative
4import Control.Monad 6import Control.Monad
5import Data.Function 7import Data.Function
6#ifdef THREAD_DEBUG 8#ifdef THREAD_DEBUG
@@ -89,6 +91,52 @@ forkPingMachine label idle timeout = do
89 , pingStarted = started 91 , pingStarted = started
90 } 92 }
91 93
94-- | like 'forkPingMachine' but the timeout and idle parameters can be changed dynamically
95-- Unlike 'forkPingMachine', 'forkPingMachineDynamic' always launches a thread
96-- regardless of idle value.
97forkPingMachineDynamic
98 :: String
99 -> TVar PingInterval -- ^ Milliseconds of idle before a ping is considered necessary.
100 -> TVar TimeOut -- ^ Milliseconds after 'PingIdle' before we signal 'PingTimeOut'.
101 -> IO PingMachine
102forkPingMachineDynamic label idleV timeoutV = do
103 d <- interruptibleDelay
104 flag <- atomically $ newTVar False
105 canceled <- atomically $ newTVar False
106 event <- atomically newEmptyTMVar
107 started <- atomically $ newEmptyTMVar
108 void . forkIO $ do
109 myThreadId >>= flip labelThread ("Ping." ++ label) -- ("ping.watchdog")
110 (>>=) (atomically (readTMVar started)) $ flip when $ do
111 fix $ \loop -> do
112 atomically $ writeTVar flag False
113 (idle,timeout) <- atomically $ (,) <$> readTVar idleV <*> readTVar timeoutV
114 fin <- startDelay d (1000*idle)
115 (>>=) (atomically (readTMVar started)) $ flip when $ do
116 if (not fin) then loop
117 else do
118 -- Idle event
119 atomically $ do
120 tryTakeTMVar event
121 putTMVar event PingIdle
122 writeTVar flag True
123 fin <- startDelay d (1000*timeout)
124 (>>=) (atomically (readTMVar started)) $ flip when $ do
125 me <- myThreadId
126 if (not fin) then loop
127 else do
128 -- Timeout event
129 atomically $ do
130 tryTakeTMVar event
131 writeTVar flag False
132 putTMVar event PingTimeOut
133 return PingMachine
134 { pingFlag = flag
135 , pingInterruptible = d
136 , pingEvent = event
137 , pingStarted = started
138 }
139
92-- | Terminate the watchdog thread. Call this upon connection close. 140-- | Terminate the watchdog thread. Call this upon connection close.
93-- 141--
94-- You should ensure no threads are waiting on 'pingWait' because there is no 142-- You should ensure no threads are waiting on 'pingWait' because there is no