Skip to content

Commit a0886b1

Browse files
authored
Merge pull request #18 from Julow/eio-env-as-var
eio: Add '--eio-env-as-fiber-var' Eio_main.run now also sets the variable if passed. It also creates a switch and initializes the sw variable if specified with --eio-sw-as-fiber-var.
2 parents 323ea89 + f533bd4 commit a0886b1

File tree

4 files changed

+103
-36
lines changed

4 files changed

+103
-36
lines changed

bin/lwt_to_direct_style/concurrency_backend.ml

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@ open Parsetree
44
open Ast_helper
55
open Ocamlformat_utils.Ast_utils
66

7-
let eio ~eio_sw_as_fiber_var add_comment =
7+
let eio ~eio_sw_as_fiber_var ~eio_env_as_fiber_var add_comment =
88
let used_eio_std = ref false in
9-
let fiber_ident i =
9+
let eio_std_ident mod_ i =
1010
used_eio_std := true;
11-
[ "Fiber"; i ]
12-
in
13-
let promise_ident i =
14-
used_eio_std := true;
15-
[ "Promise"; i ]
11+
[ mod_; i ]
1612
in
13+
let fiber_ident = eio_std_ident "Fiber"
14+
and promise_ident = eio_std_ident "Promise"
15+
and switch_ident = eio_std_ident "Switch" in
1716
let add_comment fmt = Format.kasprintf add_comment fmt in
1817
let add_comment_dropped_exp ~label exp =
1918
add_comment "Dropped expression (%s): [%s]." label
@@ -25,12 +24,29 @@ let eio ~eio_sw_as_fiber_var add_comment =
2524
let get_current_switch () =
2625
match eio_sw_as_fiber_var with
2726
| Some ident ->
28-
mk_apply_simple [ "Option"; "get" ]
29-
[ mk_apply_simple [ "Fiber"; "get" ] [ Exp.ident (mk_loc ident) ] ]
27+
mk_apply_simple
28+
[ "Stdlib"; "Option"; "get" ]
29+
[ mk_apply_simple (fiber_ident "get") [ Exp.ident (mk_loc ident) ] ]
3030
| None ->
3131
add_comment "[sw] (of type Switch.t) must be propagated here.";
3232
mk_exp_ident [ "sw" ]
3333
in
34+
let get_current_switch_arg () =
35+
(Labelled (mk_loc "sw"), get_current_switch ())
36+
in
37+
let env field =
38+
let env_exp =
39+
match eio_env_as_fiber_var with
40+
| Some ident ->
41+
mk_apply_simple
42+
[ "Stdlib"; "Option"; "get" ]
43+
[ mk_apply_simple (fiber_ident "get") [ Exp.ident (mk_loc ident) ] ]
44+
| None ->
45+
add_comment "[env] must be propagated from the main loop";
46+
mk_exp_ident [ "env" ]
47+
in
48+
Exp.send env_exp (mk_loc field)
49+
in
3450
object
3551
method both ~left ~right =
3652
mk_apply_simple (fiber_ident "pair") [ left; right ]
@@ -40,9 +56,7 @@ let eio ~eio_sw_as_fiber_var add_comment =
4056
method async process_f =
4157
Exp.apply
4258
(mk_exp_ident (fiber_ident "fork"))
43-
[
44-
(Labelled (mk_loc "sw"), get_current_switch ()); (Nolabel, process_f);
45-
]
59+
[ get_current_switch_arg (); (Nolabel, process_f) ]
4660

4761
method wait () =
4862
add_comment
@@ -73,9 +87,9 @@ let eio ~eio_sw_as_fiber_var add_comment =
7387
method sleep d = mk_apply_simple [ "Eio_unix"; "sleep" ] [ d ]
7488

7589
method with_timeout d f =
76-
add_comment "[env] must be propagated from the main loop";
77-
let clock = Exp.send (mk_exp_ident [ "env" ]) (mk_loc "mono_clock") in
78-
mk_apply_simple [ "Eio"; "Time"; "with_timeout_exn" ] [ clock; d; f ]
90+
mk_apply_simple
91+
[ "Eio"; "Time"; "with_timeout_exn" ]
92+
[ env "mono_clock"; d; f ]
7993

8094
method timeout_exn = mk_longident [ "Eio"; "Time"; "Timeout" ]
8195

@@ -146,7 +160,7 @@ let eio ~eio_sw_as_fiber_var add_comment =
146160
in
147161
mk_apply_ident
148162
[ "Eio_unix"; "Fd"; "of_unix" ]
149-
([ (Labelled (mk_loc "sw"), get_current_switch ()) ]
163+
([ get_current_switch_arg () ]
150164
@ blocking_arg
151165
@ [
152166
(Labelled (mk_loc "close_unix"), mk_constr_exp [ "true" ]);
@@ -163,19 +177,37 @@ let eio ~eio_sw_as_fiber_var add_comment =
163177
method fd_close fd = mk_apply_simple [ "Eio_unix"; "Fd" ] [ fd ]
164178

165179
method main_run promise =
180+
let with_binding var_ident x body =
181+
let var = Exp.ident (mk_loc var_ident) in
182+
mk_apply_simple (fiber_ident "with_binding") [ var; x; mk_thunk body ]
183+
in
166184
add_comment
167185
"[Eio_main.run] argument used to be a [Lwt] promise and is now a \
168186
[fun]. Make sure no asynchronous or IO calls are done outside of this \
169187
[fun].";
170-
(match eio_sw_as_fiber_var with
171-
| Some ident ->
172-
add_comment
173-
"Make sure to create a [Switch.t] and store it in fiber variable \
174-
[%a]."
175-
Ocamlformat_utils.Parsing.Printast.fmt_longident ident
176-
| None -> ());
188+
let wrap_sw_fiber_var k =
189+
match eio_sw_as_fiber_var with
190+
| Some var_ident ->
191+
let fun_sw =
192+
mk_fun ~arg_name:"sw" (fun sw -> with_binding var_ident sw k)
193+
in
194+
mk_apply_ident (switch_ident "run")
195+
[
196+
(Labelled (mk_loc "name"), mk_const_string "main");
197+
(Nolabel, fun_sw);
198+
]
199+
| None -> k
200+
in
201+
let wrap_env_fiber_var env k =
202+
match eio_env_as_fiber_var with
203+
| Some var_ident -> with_binding var_ident env k
204+
| None -> k
205+
in
177206
mk_apply_simple [ "Eio_main"; "run" ]
178-
[ mk_fun ~arg_name:"env" (fun _env -> promise) ]
207+
[
208+
mk_fun ~arg_name:"env" (fun env ->
209+
wrap_env_fiber_var env (wrap_sw_fiber_var promise));
210+
]
179211

180212
method input_io_of_fd fd =
181213
Exp.constraint_

bin/lwt_to_direct_style/main.ml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
let main migrate eio_sw_as_fiber_var =
2-
let backend = Concurrency_backend.eio ~eio_sw_as_fiber_var in
1+
let main migrate eio_sw_as_fiber_var eio_env_as_fiber_var =
2+
let backend =
3+
Concurrency_backend.eio ~eio_sw_as_fiber_var ~eio_env_as_fiber_var
4+
in
35
let modify_ast ~fname = Ast_rewrite.rewrite_lwt_uses ~fname ~backend in
46
let units = function
57
| "Lwt" -> true
@@ -31,6 +33,17 @@ let opt_eio_sw_as_fiber_var =
3133
& opt (some ident_conv) None
3234
& info ~doc ~docv:"Fiber.key" [ "eio-sw-as-fiber-var" ])
3335

36+
let opt_eio_env_as_fiber_var =
37+
let doc =
38+
"Eio only: Pass the environment as a Fiber variable. It will be queried \
39+
everytime the environment is needed. Argument must be a fully-qualified \
40+
OCaml identifier pointing to a value of type 'Switch.t Fiber.key'."
41+
in
42+
Arg.(
43+
value
44+
& opt (some ident_conv) None
45+
& info ~doc ~docv:"Fiber.key" [ "eio-env-as-fiber-var" ])
46+
3447
let opt_migrate =
3548
let doc = "Modify the source code instead of printing occurrences of Lwt." in
3649
Arg.(value & flag & info ~doc [ "migrate" ])
@@ -41,6 +54,9 @@ let cmd =
4154
in
4255
let info = Cmd.info "lwt-to-direct-style" ~version:"%%VERSION%%" ~doc in
4356
Cmd.v info
44-
Term.(term_result (const main $ opt_migrate $ opt_eio_sw_as_fiber_var))
57+
Term.(
58+
term_result
59+
(const main $ opt_migrate $ opt_eio_sw_as_fiber_var
60+
$ opt_eio_env_as_fiber_var))
4561

4662
let () = exit (Cmd.eval cmd)

test/lwt_to_direct_style/eio-switch.t/run.t

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,36 @@ Make a writable directory tree:
33
$ cd out
44

55
$ dune build @ocaml-index
6-
$ lwt-to-direct-style --migrate --eio-sw-as-fiber-var Fiber_var.sw
6+
$ lwt-to-direct-style --migrate --eio-sw-as-fiber-var Fiber_var.sw --eio-env-as-fiber-var Fiber_var.env
77
Formatted 1 files
8-
Warning: main.ml: 2 occurrences have not been rewritten.
9-
Lwt_io.read (line 9 column 12)
10-
Lwt_io.printf (line 10 column 3)
8+
Warning: main.ml: 5 occurrences have not been rewritten.
9+
Lwt_io.open_file (line 8 column 13)
10+
Lwt_io.input (line 8 column 36)
11+
Lwt_io.close (line 9 column 3)
12+
Lwt_io.read (line 15 column 12)
13+
Lwt_io.printf (line 16 column 3)
1114

1215
$ cat main.ml
1316
open Eio.Std
1417

1518
let async_process _ = ()
1619

20+
let _f _ =
21+
Eio.Time.with_timeout_exn
22+
(Stdlib.Option.get (Fiber.get Fiber_var.env))#mono_clock 1.0 (fun () -> 42)
23+
24+
let _f fname =
25+
let fd = Lwt_io.open_file ~mode:Lwt_io.input fname in
26+
Lwt_io.close fd
27+
1728
let main () =
1829
Fiber.fork
19-
~sw:(Option.get (Fiber.get Fiber_var.sw))
30+
~sw:(Stdlib.Option.get (Fiber.get Fiber_var.sw))
2031
(fun () -> async_process 1);
2132
let fd =
2233
fun ?blocking:x1 ?set_flags:x2 ->
2334
Eio_unix.Fd.of_unix
24-
~sw:(Option.get (Fiber.get Fiber_var.sw))
35+
~sw:(Stdlib.Option.get (Fiber.get Fiber_var.sw))
2536
?blocking:x1 ~close_unix:true
2637
(* TODO: lwt-to-direct-style: Labelled argument ?set_flags was dropped. *)
2738
Unix.stdin
@@ -34,6 +45,8 @@ Make a writable directory tree:
3445
3546
let () =
3647
Eio_main.run (fun env ->
37-
(* TODO: lwt-to-direct-style: [Eio_main.run] argument used to be a [Lwt] promise and is now a [fun]. Make sure no asynchronous or IO calls are done outside of this [fun]. *)
38-
(* TODO: lwt-to-direct-style: Make sure to create a [Switch.t] and store it in fiber variable ["Fiber_var.sw"]. *)
39-
main ())
48+
Fiber.with_binding Fiber_var.env env (fun () ->
49+
Switch.run ~name:"main" (fun sw ->
50+
Fiber.with_binding Fiber_var.sw sw (fun () ->
51+
(* TODO: lwt-to-direct-style: [Eio_main.run] argument used to be a [Lwt] promise and is now a [fun]. Make sure no asynchronous or IO calls are done outside of this [fun]. *)
52+
main ()))))

test/lwt_to_direct_style/eio-switch.t/src/main.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ open Lwt.Syntax
22

33
let async_process _ = Lwt.return ()
44

5+
let _f _ = Lwt_unix.with_timeout 1.0 (fun () -> Lwt.return 42)
6+
7+
let _f fname =
8+
let* fd = Lwt_io.open_file ~mode:Lwt_io.input fname in
9+
Lwt_io.close fd
10+
511
let main () =
612
Lwt.async (fun () -> async_process 1);
713
let fd = Lwt_unix.of_unix_file_descr Unix.stdin in

0 commit comments

Comments
 (0)