Skip to content

Commit

Permalink
Be able to perform unhandled effects
Browse files Browse the repository at this point in the history
  • Loading branch information
dinosaure committed Sep 11, 2023
1 parent 2bf366a commit cbc666f
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 10 deletions.
10 changes: 4 additions & 6 deletions lib/miou.ml
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ and pool = {

and continue = Continue : Syscall_uid.t * (unit -> unit) -> continue
and events = { select: unit -> continue list; interrupt: unit -> unit }
and effect = Effect : 'a Effect.t -> effect
and uid = Syscall_uid.t

type _ Effect.t += Syscall : (unit -> 'a) -> 'a syscall Effect.t
Expand All @@ -340,8 +339,6 @@ type _ Effect.t += Syscall_exists : Syscall_uid.t -> bool Effect.t

let dummy_events = { select= Fun.const []; interrupt= ignore }

exception Invalid_effect of effect

module Domain = struct
module Uid = Domain_uid

Expand Down Expand Up @@ -769,9 +766,7 @@ module Domain = struct
else k (State.Fail Not_a_child)
| Suspend _ -> k State.Intr
| Ownership action -> ownership current k action
| effect ->
Logs.err (fun m -> m "Unhandled effect");
k (State.Fail (Invalid_effect (Effect effect)))
| effect -> k (State.None effect)
in
{ State.perform }

Expand Down Expand Up @@ -857,6 +852,9 @@ module Domain = struct
| State.Suspended _ as state ->
let state = invariant prm state in
add_task domain (Suspended (prm, state))
| State.Unhandled _ as state ->
let state = invariant prm state in
add_task domain (Suspended (prm, state))

let transfer_system_task pool domain (Continue (uid, fn0)) =
match Hashtbl.find domain.system_tasks uid with
Expand Down
23 changes: 20 additions & 3 deletions lib/state.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type ('a, 'b) continuation = ('a, 'b) Effect.Shallow.continuation
type 'a t =
| Finished of ('a, exn) result
| Suspended : ('a, 'b) continuation * 'a Effect.t -> 'b t
| Unhandled : ('a, 'b) continuation * 'a -> 'b t

let effc eff k = Suspended (k, eff)

Expand Down Expand Up @@ -36,6 +37,9 @@ let discontinue_with : ('c, 'a) continuation -> exn -> 'a t =
let suspended_with : ('c, 'a) continuation -> 'c Effect.t -> 'a t =
fun k e -> Suspended (k, e)

let unhandled_with : ('c, 'a) continuation -> 'c -> 'a t =
fun k v -> Unhandled (k, v)

let pure res = Finished res

let make k v =
Expand All @@ -47,6 +51,7 @@ type 'a step =
| Fail of exn
| Intr
| Cont : 'a Effect.t -> 'a step
| None : 'a Effect.t -> 'a step
| Yield : unit step

type ('a, 'b) k = ('a step -> 'b t) -> 'a Effect.t -> 'b t
Expand All @@ -55,13 +60,17 @@ type perform = { perform: 'a 'b. ('a, 'b) k } [@@unboxed]
let once : type a. perform:perform -> a t -> a t =
fun ~perform -> function
| Finished _ as finished -> finished
| Unhandled (fn, v) -> continue_with fn v
| Suspended (fn, e) as state ->
let k : type c. (c, a) continuation -> c step -> a t =
fun fn -> function
| Send v -> continue_with fn v
| Fail exn -> discontinue_with fn exn
| Intr -> state
| Cont e -> suspended_with fn e
| None eff ->
let v = Effect.perform eff in
unhandled_with fn v
| Yield -> continue_with fn ()
in
perform.perform (k fn) e
Expand All @@ -80,15 +89,22 @@ let run : type a. quanta:int -> perform:perform -> a t -> a t =
| Send v -> continue_with fn v
| Fail e -> discontinue_with fn e
| Cont e -> suspended_with fn e
| None e ->
let v = Effect.perform e in
unhandled_with fn v
| Intr -> raise_notrace Break
| Yield -> raise_notrace (Yield (continue_with fn ()))
in
let quanta = ref quanta and state = ref state in
try
while !quanta > 0 && is_finished !state = false do
let (Suspended (fn, e)) = !state in
state := perform.perform (k fn) e;
quanta := !quanta - 1
match !state with
| Suspended (fn, e) ->
state := perform.perform (k fn) e;
quanta := !quanta - 1
| Unhandled (fn, v) ->
state := continue_with fn v;
quanta := !quanta - 1
done;
!state
with
Expand All @@ -102,3 +118,4 @@ let run : type a. quanta:int -> perform:perform -> a t -> a t =
let fail ~exn = function
| Finished _ -> Finished (Error exn)
| Suspended (k, _) -> discontinue_with k exn
| Unhandled (k, _) -> discontinue_with k exn
2 changes: 2 additions & 0 deletions lib/state.mli
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type ('a, 'b) continuation
type 'a t = private
| Finished of ('a, exn) result
| Suspended : ('a, 'b) continuation * 'a Effect.t -> 'b t
| Unhandled : ('a, 'b) continuation * 'a -> 'b t

val make : ('a -> 'b) -> 'a -> 'b t
(** [make fn value] makes a new {i function state} by executing the function
Expand All @@ -99,6 +100,7 @@ type 'a step =
| Fail of exn
| Intr
| Cont : 'a Effect.t -> 'a step
| None : 'a Effect.t -> 'a step
| Yield : unit step

type ('a, 'b) k = ('a step -> 'b t) -> 'a Effect.t -> 'b t
Expand Down
1 change: 1 addition & 0 deletions test/core/core.t
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@
Fatal error: exception Miou.Still_has_children
[2]
$ ./t25.exe
$ ./t28.exe
8 changes: 7 additions & 1 deletion test/core/dune
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@
(modules t27)
(libraries miou))

(executable
(name t28)
(modules t28)
(libraries miou))

(cram
(package miou)
(deps
Expand Down Expand Up @@ -155,4 +160,5 @@
t22.exe
t23.exe
t24.exe
t25.exe))
t25.exe
t28.exe))
18 changes: 18 additions & 0 deletions test/core/t28.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
type _ Effect.t += Foo : unit Effect.t

let prgm () =
let prm = Miou.call_cc @@ fun () -> Effect.perform Foo in
Miou.await_exn prm

let handler fn v =
let open Effect.Deep in
let retc = Fun.id in
let exnc = raise in
let effc : type c. c Effect.t -> ((c, 'a) continuation -> 'b) option =
function
| Foo -> Some (fun k -> continue k ())
| _ -> None
in
match_with fn v { retc; exnc; effc }

let () = handler (fun () -> Miou.run prgm) ()

0 comments on commit cbc666f

Please sign in to comment.