summaryrefslogtreecommitdiff
path: root/app/Foobar/Services/Coalescing.hs
diff options
context:
space:
mode:
Diffstat (limited to 'app/Foobar/Services/Coalescing.hs')
-rw-r--r--app/Foobar/Services/Coalescing.hs46
1 files changed, 46 insertions, 0 deletions
diff --git a/app/Foobar/Services/Coalescing.hs b/app/Foobar/Services/Coalescing.hs
new file mode 100644
index 0000000..c44c5eb
--- /dev/null
+++ b/app/Foobar/Services/Coalescing.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE OverloadedRecordDot, DuplicateRecordFields #-}
+
+-- |
+-- Module : Foobar.Services.Coalescing
+-- Description: Coalesce multiple events using a timeout.
+
+module Foobar.Services.Coalescing
+ ( EventScheduler
+ , mkEventScheduler
+ , scheduleEvent
+ ) where
+
+import Data.IORef (IORef, newIORef, readIORef, writeIORef)
+import Data.Word (Word32)
+
+import qualified GI.GLib as GLib
+
+-- | Management structure for coalescing events.
+data EventScheduler
+ = EventScheduler { delay :: !Int
+ , sourceId :: !(IORef (Maybe Word32)) }
+
+-- | Create a new event scheduler for coalescing events.
+mkEventScheduler
+ :: Int -- ^ Delay for scheduling events in milliseconds.
+ -> IO EventScheduler -- ^ The event scheduler structure.
+mkEventScheduler delay' = EventScheduler delay' <$> newIORef Nothing
+
+-- | Schedule an event.
+--
+-- If there is already an event scheduled, the two are coalesced.
+scheduleEvent
+ :: EventScheduler -- ^ The event scheduler.
+ -> IO () -- ^ The event to be scheduled.
+ -> IO ()
+scheduleEvent s event = do
+ existingId <- readIORef s.sourceId
+ let sourceFunc :: GLib.SourceFunc
+ sourceFunc = do
+ event
+ writeIORef s.sourceId Nothing
+ pure GLib.SOURCE_REMOVE
+ case existingId of
+ Just _ -> pure ()
+ Nothing -> do newId <- GLib.timeoutAdd GLib.PRIORITY_DEFAULT (fromIntegral s.delay) sourceFunc
+ writeIORef s.sourceId (Just newId)