0 | module IO.Async.Loop.TimerST
2 | import Data.SortedMap
3 | import Data.Linear.Ref1
4 | import Data.Linear.Traverse1
14 | record TimerST where
17 | map : SortedMap Integer (List (Nat, IO1 ()))
19 | schedule_ : Integer -> IO1 () -> TimerST -> TimerST
20 | schedule_ ns act (TST id m) =
22 | Nothing => TST (S id) $
insert ns [(id,act)] m
23 | Just ps => TST (S id) $
insert ns ((id,act)::ps) m
25 | drop_ : Integer -> Nat -> TimerST -> TimerST
26 | drop_ ns x (TST id m) =
29 | Just vs => case filter ((x /=) . fst) vs of
30 | [] => TST id $
delete ns m
31 | ws => TST id $
insert ns ws m
36 | let now # t := ioToF1 (clockTime Monotonic) t
39 | nextDue : Integer -> IORef TimerST -> IO1 (Either Integer (List (Nat,IO1 ())))
41 | let (TST id m) # t := read1 r t
42 | in case leftMost m of
43 | Nothing => Left 0 # t
44 | Just (due,ps) => case ns >= due of
46 | let _ # t := write1 r (TST id $
delete due m) t
48 | False => Left (due - ns) # t
61 | timer t = let st # t := ref1 (TST 0 empty) t in T st # t
63 | parameters (ti : Timer)
69 | schedule : Clock Duration -> IO1 () -> IO1 (IO1 ())
70 | schedule dur act t =
71 | let ns # t := nanos t
72 | end := ns + toNano dur
73 | in case end <= ns of
74 | True => let _ # t := act t in unit1 # t
76 | let tst # t := read1 ti.ref t
77 | _ # t := write1 ti.ref (schedule_ end act tst) t
78 | in mod1 ti.ref (drop_ end tst.id) # t
81 | runDue : Integer -> IO1 Integer
83 | case nextDue now ti.ref t of
85 | let _ # t := traverse1_ snd ps t
86 | in runDue (assert_smaller now now) t
87 | Left rem # t => rem # t
91 | runDueTimers : IO1 Integer
93 | let st # t := read1 ti.ref t
94 | in case leftMost st.map of
97 | let now # t := nanos t
98 | in case now >= ns of
99 | False => (ns - now) # t
100 | True => runDue now t