Skip to content

Commit

Permalink
Handle effects even if they appear in another domain
Browse files Browse the repository at this point in the history
  • Loading branch information
dinosaure committed Sep 11, 2023
1 parent cbc666f commit 7d89258
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 6 deletions.
16 changes: 12 additions & 4 deletions lib/miou.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
let failwith fmt = Format.kasprintf failwith fmt
let str fmt = Format.kasprintf Fun.id fmt

external apply : ('a -> 'b) -> 'a -> 'b = "%apply"
external reraise : exn -> unit = "%reraise"

module Queue = Queue
Expand Down Expand Up @@ -331,13 +332,15 @@ and pool = {

and continue = Continue : Syscall_uid.t * (unit -> unit) -> continue
and events = { select: unit -> continue list; interrupt: unit -> unit }
and handler = { handler: 'u 'v. ('u -> 'v) -> 'u -> 'v } [@@unboxed]
and uid = Syscall_uid.t

type _ Effect.t += Syscall : (unit -> 'a) -> 'a syscall Effect.t
type _ Effect.t += Suspend : 'a syscall -> 'a Effect.t
type _ Effect.t += Syscall_exists : Syscall_uid.t -> bool Effect.t

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

module Domain = struct
module Uid = Domain_uid
Expand Down Expand Up @@ -853,6 +856,8 @@ module Domain = struct
let state = invariant prm state in
add_task domain (Suspended (prm, state))
| State.Unhandled _ as state ->
Logs.debug (fun m ->
m "%a suspended due to unhandled effect" Promise.pp prm);
let state = invariant prm state in
add_task domain (Suspended (prm, state))

Expand Down Expand Up @@ -993,7 +998,7 @@ module Pool = struct
goes back to sleep until the next signal. Domains can communicate with
[dom0] (the launcher) by signaling that all domains are dormant ([idle]).
Finally, [dom0] can communicate with the domains asking to stop. *)
let worker pool domain =
let worker pool domain _ =
let exception Exit in
try
while true do
Expand Down Expand Up @@ -1053,6 +1058,7 @@ module Pool = struct
wait pool

let make ?(quanta = 2) ?(g = Random.State.make_self_init ())
?(handler = dummy_handler)
?(domains = max 0 (Stdlib.Domain.recommended_domain_count () - 1)) events
=
let domains = List.init domains @@ fun _ -> Domain.make ~quanta ~g events in
Expand All @@ -1068,7 +1074,9 @@ module Pool = struct
; domains
}
in
let spawn domain = Stdlib.Domain.spawn @@ fun () -> worker pool domain in
let spawn domain =
Stdlib.Domain.spawn (handler.handler (worker pool domain))
in
(pool, List.map spawn domains)
end

Expand Down Expand Up @@ -1204,12 +1212,12 @@ let await_only_domains dom0 =
else true

let run ?(quanta = quanta) ?(events = Fun.const dummy_events)
?(g = Random.State.make_self_init ()) ?domains fn =
?(g = Random.State.make_self_init ()) ?domains ?handler fn =
Domain.Uid.reset ();
let dom0 = Domain.make ~quanta ~g events in
let prm0 = Promise.make ~resources:[] ~runner:dom0.uid () in
Domain.add_task dom0 (Arrived (prm0, fn));
let pool, domains = Pool.make ~quanta ~g ?domains events in
let pool, domains = Pool.make ~quanta ~g ?domains ?handler events in
while Promise.is_pending prm0 do
Domain.run pool dom0;
if await_only_domains dom0 && Domain.system_tasks_suspended dom0 = false
Expand Down
2 changes: 2 additions & 0 deletions lib/miou.mli
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ val task : 'a syscall -> (unit -> unit) -> continue
represented by the given [syscall]. *)

type events = { select: unit -> continue list; interrupt: unit -> unit }
type handler = { handler: 'a 'b. ('a -> 'b) -> 'a -> 'b } [@@unboxed]

val is_pending : 'a syscall -> bool
(** [is_pending syscall] checks the status of the suspension point. A suspension
Expand Down Expand Up @@ -787,5 +788,6 @@ val run :
-> ?events:(Domain.Uid.t -> events)
-> ?g:Random.State.t
-> ?domains:int
-> ?handler:handler
-> (unit -> 'a)
-> 'a
4 changes: 2 additions & 2 deletions test/core/t28.ml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
type _ Effect.t += Foo : unit Effect.t

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

let handler fn v =
Expand All @@ -15,4 +15,4 @@ let handler fn v =
in
match_with fn v { retc; exnc; effc }

let () = handler (fun () -> Miou.run prgm) ()
let () = handler (fun () -> Miou.run ~handler:{ Miou.handler } prgm) ()

0 comments on commit 7d89258

Please sign in to comment.