module Development.IDE.Core.Debouncer
( Debouncer
, newDebouncer
, registerEvent
) where
import Control.Concurrent.Extra
import Control.Concurrent.Async
import Control.Exception
import Control.Monad.Extra
import Data.Hashable
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as Map
import System.Time.Extra
newtype Debouncer k = Debouncer (Var (HashMap k (Async ())))
newDebouncer :: IO (Debouncer k)
newDebouncer = do
m <- newVar Map.empty
pure $ Debouncer m
registerEvent :: (Eq k, Hashable k) => Debouncer k -> Seconds -> k -> IO () -> IO ()
registerEvent (Debouncer d) delay k fire = modifyVar_ d $ \m -> mask_ $ do
whenJust (Map.lookup k m) cancel
a <- asyncWithUnmask $ \unmask -> unmask $ do
sleep delay
fire
modifyVar_ d (pure . Map.delete k)
pure $ Map.insert k a m