8 | module IO.Async.Loop.Poller
10 | import Data.Linear.Ref1
11 | import Data.SortedMap
13 | import IO.Async.Internal.Ref
17 | import System.Posix.File.Prim
18 | import System.Posix.Poll.Prim
27 | dieOnErr : E1 World [Errno] a -> IO1 a
31 | E (Here x) t => ioToF1 (die "Error: \{errorText x} (\{errorName x})") t
35 | FileHandle = PollEvent -> IO1 ()
39 | hdummy = \_ => unit1
47 | constructor MkPoller
49 | pollWait : Clock Duration -> IO1 ()
54 | -> (autoClose : Bool)
55 | -> (cb : Either Errno PollEvent -> IO1 ())
67 | handles : IORef (SortedMap Fd (PollEvent, FileHandle))
69 | parameters (p : Posix)
72 | getHandle : Fd -> IO1 (Maybe (PollEvent,FileHandle))
74 | let m # t := read1 p.handles t
77 | handleEvs : List PollPair -> IO1 ()
78 | handleEvs [] t = () # t
79 | handleEvs (PP fd ev::es) t =
80 | let Just (_,h) # t := getHandle fd t | Nothing # t => handleEvs es t
85 | pollWaitImpl : (timeout : Clock Duration) -> IO1 ()
87 | let ms := seconds to * 1000 + (nanoseconds to `div` 1_000_000)
88 | fds # t := read1 p.handles t
89 | pairs := (\(fd,e,_) => PP fd e) <$> kvList fds
90 | vs # t := dieOnErr (pollList pairs (cast ms)) t
95 | let m # t := read1 p.handles t
96 | in if null m then () # t else pollWaitImpl (makeDuration 0 0) t
98 | cleanup : Posix -> Fd -> IO1 ()
101 | let x # t := read1 p.handles t
102 | True # t := caswrite1 p.handles x (delete fd x) t | _ # t => cleanup p fd t
105 | insrt : Posix -> Fd -> PollEvent -> FileHandle -> IO1 ()
106 | insrt p fd ev fh t =
108 | let x # t := read1 p.handles t
109 | True # t := caswrite1 p.handles x (insert fd (ev,fh) x) t | _ # t => cleanup p fd t
116 | parameters (p : Posix)
120 | (cb : Either Errno PollEvent -> IO1 ())
126 | closefd = when1 autoClose (toF1 $
close' fd)
133 | let _ # t := Poller.cleanup p fd t
134 | _ # t := cb (Right e) t
141 | let _ # t := Poller.cleanup p fd t
144 | pollFileImpl : IO1 (IO1 ())
154 | r # t := ref1 True t
155 | _ # t := insrt p fd ev (once r . act) t
156 | in once r (cleanup p fd) # t
160 | posixPoller : IO1 Poller
162 | let ref # t := ref1 SortedMap.empty t
164 | in MkPoller (pollImpl px) (pollWaitImpl px) unit1 (pollFileImpl px) # t