@@ -34,23 +34,50 @@ newAsyncDebouncer = Debouncer . asyncRegisterEvent <$> STM.newIO
34
34
35
35
-- | Register an event that will fire after the given delay if no other event
36
36
-- for the same key gets registered until then.
37
- asyncRegisterEvent :: (Eq k , Hashable k ) => STM. Map k (TVar (Seconds , IO () )) -> Seconds -> k -> IO () -> IO ()
37
+ asyncRegisterEvent
38
+ :: (Eq k , Hashable k )
39
+ => STM. Map k (TVar (Maybe (Seconds , IO () )))
40
+ -> Seconds
41
+ -> k
42
+ -> IO ()
43
+ -> IO ()
38
44
asyncRegisterEvent d delay k fire = join $ atomicallyNamed " debouncer - register" $ do
45
+ -- The previous TVar for this key, if any
39
46
prev <- STM. lookup k d
40
47
case prev of
41
- Just v -> writeTVar v (delay, fire) >> return (pure () )
48
+ Just v -> do
49
+ current <- readTVar v
50
+ case current of
51
+ -- Not empty, means that there is a thread running the actions
52
+ Just _ -> writeTVar v (Just (delay, fire)) >> return (pure () )
53
+ -- Empty = no thread. We need to start one for running the action
54
+ Nothing -> writeTVar v (Just (delay, fire)) >> return (restart v)
55
+
56
+ -- No previous TVar, we need to insert one and restart a thread for running the action
42
57
Nothing
43
58
| delay == 0 -> return fire
44
59
| otherwise -> do
45
- var <- newTVar (delay, fire)
60
+ var <- newTVar (Just ( delay, fire) )
46
61
STM. insert var k d
47
- return $ void $ async $
62
+ return (restart var)
63
+ where
64
+ -- | Restart a thread to run the action stored in the given TVar
65
+ -- Once the action is done, the thread dies.
66
+ -- Assumes the Tvar is not empty
67
+ restart var =
68
+ void $ async $
48
69
join $ atomicallyNamed " debouncer - sleep" $ do
49
- (s,act) <- readTVar var
50
- unsafeIOToSTM $ sleep s
51
- return $ do
52
- atomically (STM. delete k d)
53
- act
70
+ contents <- readTVar var
71
+ case contents of
72
+ Nothing -> error " impossible"
73
+ Just (s,act) -> do
74
+ -- sleep for the given delay
75
+ -- If the TVar is written while sleeping,
76
+ -- the transaction will restart
77
+ unsafeIOToSTM $ sleep s
78
+ -- we are done - empty the TVar before exiting
79
+ writeTVar var Nothing
80
+ return act
54
81
55
82
-- | Debouncer used in the DAML CLI compiler that emits events immediately.
56
83
noopDebouncer :: Debouncer k
0 commit comments