summaryrefslogtreecommitdiff
path: root/RealTimeQueue.hs
diff options
context:
space:
mode:
Diffstat (limited to 'RealTimeQueue.hs')
-rw-r--r--RealTimeQueue.hs52
1 files changed, 52 insertions, 0 deletions
diff --git a/RealTimeQueue.hs b/RealTimeQueue.hs
new file mode 100644
index 0000000..dc40c84
--- /dev/null
+++ b/RealTimeQueue.hs
@@ -0,0 +1,52 @@
1module RealTimeQueue where
2import BasePrelude hiding ((<>))
3import System.Clock
4import Data.IntPSQ as Q
5import Control.Monad.IO.Class
6import Data.Semigroup
7
8scheduleEvent :: (TimeSpec, event) -> Queue event -> Queue event
9scheduleEvent (ts, ev) (Queue q i) = Queue (Q.insert i ts ev q) (i+1)
10
11instance Semigroup (Queue event) where
12 _ <> q = q
13
14extractScheduledEvents :: TimeSpec -> TimeSpec -> Queue event -> ([(TimeSpec, event)], Queue event)
15extractScheduledEvents currentTime timeSpan = getAllScheduled
16 where
17 getAllScheduled :: Queue event -> ([(TimeSpec, event)], Queue event)
18 getAllScheduled queue@(Queue q i)
19 | isNothing $ getFirstScheduled queue = ([], queue)
20 | otherwise = let (Just (_, p, v, q')) = minView q
21 queue' = Queue q' i
22 in ([(p, v)], queue') <> getAllScheduled queue'
23
24
25 getFirstScheduled :: Queue event -> Maybe (TimeSpec, event)
26 getFirstScheduled (Queue x _) = case findMin x of
27 Nothing -> Nothing
28 Just (_, ts, _) | ts > currentTime + timeSpan -> Nothing
29 Just (_, ts, ev) -> Just (ts - currentTime, ev)
30
31type QueueRunner m event = TimeSpec -> event -> m ()
32
33scheduleEventIO :: MonadIO m => (TimeSpec, event) -> Queue event -> m (Queue event)
34scheduleEventIO (ts, ev) queue = do
35 now <- liftIO $ getTime Monotonic
36 return $ scheduleEvent (ts + now, ev) queue
37
38runScheduledIO :: MonadIO m => TimeSpec -> QueueRunner m event -> Queue event -> m (Queue event)
39runScheduledIO timeSpan runner queue = do
40 now <- liftIO $ getTime Monotonic
41 let (events, queue') = extractScheduledEvents now timeSpan queue
42 forM_ events $ \(ts, ev) -> runner (ts - now) ev
43 return queue'
44
45
46createQueue :: Queue event
47createQueue = Queue Q.empty 0
48
49data Queue event = Queue {
50 intQueue :: IntPSQ TimeSpec event,
51 nextKey :: Int
52}