4 | import Data.Linear.Deferred
5 | import Data.Linear.Unique
7 | import public IO.Async.Core
8 | import public Data.Linear.Ref1
17 | record FiberImpl (es : List Type) (a : Type) where
23 | cncl : Once World ()
26 | res : Deferred World (Outcome es a)
29 | newFiber : IO1 (FiberImpl es a)
31 | let tok # t := Unique.token1 t
32 | cncl # t := onceOf1 () t
33 | res # t := deferredOf1 (Outcome es a) t
34 | in FI tok cncl res # t
36 | toFiber : FiberImpl es a -> Fiber es a
37 | toFiber fbr = MkFiber (putOnce1 fbr.cncl ()) (observeDeferredAs1 fbr.res)
44 | data StackItem : (e : Type) -> (es,fs : List Type) -> (a,b : Type) -> Type where
47 | Bnd : (a -> Async e es b) -> StackItem e es es a b
51 | Att : StackItem e es fs a (Result es a)
54 | Inc : StackItem e es es a a
57 | Abort : StackItem e [] es () a
60 | Dec : StackItem e es es a a
64 | Hook : Async e [] () -> StackItem e es es a a
73 | data Stack : (e : Type) -> (es,fs : List Type) -> (a,b : Type) -> Type where
74 | Nil : Stack e es es a a
75 | (::) : StackItem e es fs a b -> Stack e fs gs b c -> Stack e es gs a c
79 | record FbrState (e : Type) where
81 | {0 curErrs, resErrs : List Type}
82 | {0 curType, resType : Type}
84 | fiber : FiberImpl resErrs resType
86 | comp : Async e curErrs curType
87 | stack : Stack e curErrs resErrs curType resType
91 | data RunRes : Type -> Type where
101 | Cont : FbrState e -> RunRes e
117 | interface EventLoop (0 e : Type) where
120 | spawn : (el : e) -> FbrState e -> IO1 ()
126 | runFbr : (el : EventLoop e) => e -> FbrState e -> IO1 (RunRes e)
130 | {auto el : EventLoop e}
133 | -> (Outcome es a -> IO ())
135 | runAsyncWith env act cb = runIO $
\t =>
136 | let fbr # t := newFiber t
137 | _ # t := observeDeferredAs1 fbr.res fbr.token (\o => ioToF1 $
cb o) t
138 | in spawn env (FST fbr 0 act []) t
141 | runAsync : EventLoop e => e -> Async e es a -> IO ()
142 | runAsync env as = runAsyncWith env as (\_ => pure ())
148 | record CBState (es : List Type) (a : Type) where
150 | {0 resErrs : List Type}
151 | {0 envType, resType : Type}
156 | fiber : FiberImpl resErrs resType
158 | stack : Stack envType es resErrs a resType
159 | {auto el : EventLoop envType}
161 | prepend : Async e [] a -> Stack e [] fs a b -> Stack e [] fs () b
162 | prepend act s = Bnd (const act) :: s
164 | hooks : Stack e es fs a b -> Stack e [] fs () b
165 | hooks (Hook h :: t) = prepend h (hooks t)
166 | hooks (_ :: t) = hooks t
169 | observeCancel : Once World (Outcome es a) -> Nat -> FiberImpl fs b -> IO1 (IO1 ())
170 | observeCancel o 0 f = observeOnce1 f.cncl (\_ => putOnce1 o Canceled)
171 | observeCancel _ _ _ = (unit1 #)
174 | synchronous : Outcome es a -> Fiber es a
175 | synchronous o = MkFiber unit1 (\_,cb,t => let _ # t := cb o t in unit1 # t)
179 | asynchronous : ((Result es a -> IO1 ()) -> IO1 (IO1 ())) -> IO1 (Fiber es a)
180 | asynchronous install t =
181 | let def # t := deferredOf1 (Outcome es a) t
182 | cleanup # t := install (putDeferred1 def . toOutcome) t
183 | cncl := T1.do
cleanup;
putDeferred1 def Canceled
184 | in MkFiber cncl (observeDeferredAs1 def) # t
187 | spawnCB : CBState es a -> Outcome es a -> IO1 ()
188 | spawnCB (CST env c1 c2 fbr cm st) o t =
190 | Succeeded r => let _ # t := c2 t in spawn env (FST fbr cm (Val r) st) t
191 | Error x => let _ # t := c2 t in spawn env (FST fbr cm (Err x) st) t
192 | Canceled => let _ # t := c1 t in spawn env (FST fbr 1 (Val ()) (hooks st)) t
196 | Once World (Outcome es a)
197 | -> ((Result es a -> IO1 ()) -> IO1 (IO1 ()))
199 | writeOnCB o f t = f (putOnce1 o . toOutcome) t
202 | obsOnce : Once World (Outcome es a) -> CBState es a -> IO1 (RunRes e)
203 | obsOnce o st t = let _ # t := observeOnce1 o (spawnCB st) t in Done # t
207 | finalize : FiberImpl es a -> Outcome es a -> IO1 (RunRes e)
208 | finalize fbr o t = let _ # t := putDeferred1 fbr.res o t in Done # t
213 | {auto el : EventLoop e}
216 | -> (cancelMask : Nat)
217 | -> (cedeCount : Nat)
219 | -> Stack e es fs a b
225 | {auto el : EventLoop e}
228 | -> (cancelMask : Nat)
229 | -> (cedeCount : Nat)
231 | -> Stack e es fs a b
238 | {auto el : EventLoop e}
241 | -> (cedeCount : Nat)
243 | -> Stack e es fs a b
248 | run env act cm 0 fbr st t = Cont (FST fbr cm act st) # t
253 | run env act 0 (S k) fbr st t =
254 | case completedOnce1 fbr.cncl t of
255 | False # t => runR env act 0 k fbr st t
256 | True # t => runC env act k fbr st t
260 | run env act c (S k) fbr st t = runR env act c k fbr st t
262 | runC env act cc fbr st t =
264 | UC f => run env (f fbr.token 1) 1 cc fbr (Dec::st) t
265 | Val x => case st of
266 | Bnd f :: tl => case f x of
267 | UC g => run env (g fbr.token 1) 1 cc fbr (Dec::tl) t
268 | a => run env (pure ()) 1 cc fbr (hooks st) t
269 | Att :: tl => runC env (Val $
Right x) cc fbr tl t
270 | Inc :: tl => run env (Val x) 1 cc fbr tl t
271 | _ => run env (pure ()) 1 cc fbr (hooks st) t
272 | Err x => case st of
273 | Att :: tl => runC env (Val $
Left x) cc fbr tl t
274 | Inc :: tl => run env (Err x) 1 cc fbr tl t
275 | _ => run env (pure ()) 1 cc fbr (hooks st) t
276 | _ => run env (pure ()) 1 cc fbr (hooks st) t
278 | runR env act cm cc fbr st t =
280 | Bind x f => case x of
281 | Val x => run env (f x) cm cc fbr st t
282 | Self => run env (f fbr.token) cm cc fbr st t
283 | _ => run env x cm cc fbr (Bnd f :: st) t
285 | Val x => case st of
286 | Bnd f :: tl => run env (f x) cm cc fbr tl t
287 | Inc :: tl => run env act (S cm) cc fbr tl t
288 | Dec :: tl => run env act (pred cm) cc fbr tl t
291 | Hook h :: tl => run env act cm cc fbr tl t
292 | Abort :: tl => finalize fbr Canceled t
293 | Att :: tl => run env (Val $
Right x) cm cc fbr tl t
294 | [] => finalize fbr (Succeeded x) t
296 | Err x => case st of
297 | Att :: tl => run env (Val $
Left x) cm cc fbr tl t
298 | Bnd _ :: tl => run env (Err x) cm cc fbr tl t
299 | Inc :: tl => run env act (S cm) cc fbr tl t
300 | Dec :: tl => run env act (pred cm) cc fbr tl t
303 | Hook h :: tl => run env act cm cc fbr tl t
304 | Abort :: tl => finalize fbr Canceled t
305 | [] => finalize fbr (Error x) t
309 | Start x => case x of
311 | let f2 # t := asynchronous reg t
312 | in run env (Val f2) cm cc fbr st t
313 | Cancel => run env (Val $
synchronous Canceled) cm cc fbr st t
314 | Val v => run env (Val $
synchronous (Succeeded v)) cm cc fbr st t
315 | Err x => run env (Val $
synchronous (Error x)) cm cc fbr st t
316 | Self => run env (Val $
synchronous (Succeeded fbr.token)) cm cc fbr st t
318 | let fbr2 # t := newFiber t
319 | _ # t := spawn env (FST fbr2 0 x []) t
320 | in run env (Val $
toFiber fbr2) cm cc fbr st t
323 | let r # t := ioToF1 x t
324 | in run env (terminal r) cm cc fbr st t
326 | Attempt x => run env x cm cc fbr (Att :: st) t
329 | let _ # t := putOnce1 fbr.cncl () t
330 | in run env (Val ()) cm cc fbr st t
332 | OnCncl x y => run env x cm cc fbr (Hook y :: st) t
334 | UC f => run env (f fbr.token (S cm)) (S cm) cc fbr (Dec::st) t
336 | Env => run env (Val env) cm cc fbr st t
338 | Cede => Cont (FST fbr cm (Val ()) st) # t
340 | Self => run env (Val fbr.token) cm cc fbr st t
343 | let o # t := onceOf1 (Outcome es a) t
344 | c1 # t := writeOnCB o f t
345 | c2 # t := observeCancel o cm fbr t
346 | in case peekOnce1 o t of
347 | Nothing # t => obsOnce o (CST env c1 c2 fbr cm st) t
348 | Just out # t => case out of
349 | Succeeded r => let _ # t := c2 t in run env (Val r) cm cc fbr st t
350 | Error x => let _ # t := c2 t in run env (Err x) cm cc fbr st t
351 | Canceled => let _ # t := c1 t in run env (pure ()) 1 cc fbr (hooks st) t
353 | APoll tok k x => case tok == fbr.token && k == cm of
354 | True => run env x (pred cm) cc fbr (Inc :: st) t
355 | False => run env x cm cc fbr st t
357 | runFbr env (FST fbr msk act st) = run env act msk (limit @{el}) fbr st