Skip to content

Commit 500b218

Browse files
committed
lock-less debouncer
1 parent 57cf81e commit 500b218

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

ghcide/src/Development/IDE/Core/Debouncer.hs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ module Development.IDE.Core.Debouncer
99
) where
1010

1111
import Control.Concurrent.Async
12-
import Control.Concurrent.STM.Stats (atomically, atomicallyNamed)
12+
import Control.Concurrent.STM
13+
import Control.Concurrent.STM.Stats (atomicallyNamed)
1314
import Control.Exception
1415
import Control.Monad (join)
15-
import Data.Foldable (traverse_)
1616
import Data.Hashable
17-
import qualified Focus
17+
import GHC.Conc (unsafeIOToSTM)
1818
import qualified StmContainers.Map as STM
1919
import System.Time.Extra
2020

@@ -39,20 +39,21 @@ newAsyncDebouncer = Debouncer . asyncRegisterEvent <$> STM.newIO
3939
-- If there is a pending event for the same key, the pending event will be killed.
4040
-- Events are run unmasked so it is up to the user of `registerEvent`
4141
-- to mask if required.
42-
asyncRegisterEvent :: (Eq k, Hashable k) => STM.Map k (Async ()) -> Seconds -> k -> IO () -> IO ()
43-
asyncRegisterEvent d 0 k fire = do
44-
join $ atomically $ do
45-
prev <- STM.focus Focus.lookupAndDelete k d
46-
return $ traverse_ cancel prev
47-
fire
42+
asyncRegisterEvent :: (Eq k, Hashable k) => STM.Map k (TVar (Seconds, IO())) -> Seconds -> k -> IO () -> IO ()
4843
asyncRegisterEvent d delay k fire = mask_ $ do
49-
a <- asyncWithUnmask $ \unmask -> unmask $ do
50-
sleep delay
51-
fire
52-
atomically $ STM.delete k d
53-
do
54-
prev <- atomicallyNamed "debouncer" $ STM.focus (Focus.lookup <* Focus.insert a) k d
55-
traverse_ cancel prev
44+
prev <- atomically $ STM.lookup k d
45+
case prev of
46+
Just v -> do
47+
atomicallyNamed "debouncer - reset" $ writeTVar v (delay, fire)
48+
Nothing -> do
49+
var <- newTVarIO (delay, fire)
50+
_ <- asyncWithUnmask $ \unmask -> unmask $ do
51+
join $ atomicallyNamed "debouncer - sleep" $ do
52+
(s,act) <- readTVar var
53+
unsafeIOToSTM $ sleep s
54+
STM.delete k d
55+
return act
56+
atomicallyNamed "debouncer2" $ STM.insert var k d
5657

5758
-- | Debouncer used in the DAML CLI compiler that emits events immediately.
5859
noopDebouncer :: Debouncer k

0 commit comments

Comments
 (0)