mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-10-09 00:04:06 -04:00
Allow returning a result from Eio_main.run
This is useful for e.g. cmdliner. We want to parse the command line arguments inside the event loop so that we can use Eio, but we want to call `exit` with the exit code after the loop has cleaned up.
This commit is contained in:
parent
338d74bc8c
commit
a9620bcf3d
@ -41,7 +41,7 @@ Before we start, we'll define a wrapper around `Eio_main.run` for the examples b
|
|||||||
Eio_main.run @@ fun env ->
|
Eio_main.run @@ fun env ->
|
||||||
let domain_mgr = Eio.Stdenv.domain_mgr env in
|
let domain_mgr = Eio.Stdenv.domain_mgr env in
|
||||||
fn (Eio.Domain_manager.run domain_mgr);;
|
fn (Eio.Domain_manager.run domain_mgr);;
|
||||||
val run : (((unit -> 'a) -> 'a) -> unit) -> unit = <fun>
|
val run : (((unit -> 'a) -> 'a) -> 'b) -> 'b = <fun>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Problems with Multicore Programming
|
## Problems with Multicore Programming
|
||||||
|
@ -1222,7 +1222,8 @@ let monitor_event_fd t =
|
|||||||
assert (got = 8);
|
assert (got = 8);
|
||||||
(* We just go back to sleep now, but this will cause the scheduler to look
|
(* We just go back to sleep now, but this will cause the scheduler to look
|
||||||
at the run queue again and notice any new items. *)
|
at the run queue again and notice any new items. *)
|
||||||
done
|
done;
|
||||||
|
assert false
|
||||||
|
|
||||||
let no_fallback (`Msg msg) = failwith msg
|
let no_fallback (`Msg msg) = failwith msg
|
||||||
|
|
||||||
@ -1241,7 +1242,9 @@ let with_uring ~queue_depth ?polling_timeout ?(fallback=no_fallback) fn =
|
|||||||
end;
|
end;
|
||||||
Printexc.raise_with_backtrace ex bt
|
Printexc.raise_with_backtrace ex bt
|
||||||
|
|
||||||
let rec run ?(queue_depth=64) ?n_blocks ?(block_size=4096) ?polling_timeout ?fallback main =
|
let rec run : type a.
|
||||||
|
?queue_depth:int -> ?n_blocks:int -> ?block_size:int -> ?polling_timeout:int -> ?fallback:(_ -> a) -> (_ -> a) -> a =
|
||||||
|
fun ?(queue_depth=64) ?n_blocks ?(block_size=4096) ?polling_timeout ?fallback main ->
|
||||||
Log.debug (fun l -> l "starting run");
|
Log.debug (fun l -> l "starting run");
|
||||||
let n_blocks = Option.value n_blocks ~default:queue_depth in
|
let n_blocks = Option.value n_blocks ~default:queue_depth in
|
||||||
let stdenv = stdenv ~run_event_loop:(run ~queue_depth ~n_blocks ~block_size ?polling_timeout ?fallback:None) in
|
let stdenv = stdenv ~run_event_loop:(run ~queue_depth ~n_blocks ~block_size ?polling_timeout ?fallback:None) in
|
||||||
@ -1383,6 +1386,7 @@ let rec run ?(queue_depth=64) ?n_blocks ?(block_size=4096) ?polling_timeout ?fal
|
|||||||
| _ -> None
|
| _ -> None
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
|
let result = ref None in
|
||||||
let `Exit_scheduler =
|
let `Exit_scheduler =
|
||||||
let new_fiber = Fiber_context.make_root () in
|
let new_fiber = Fiber_context.make_root () in
|
||||||
fork ~new_fiber (fun () ->
|
fork ~new_fiber (fun () ->
|
||||||
@ -1396,10 +1400,13 @@ let rec run ?(queue_depth=64) ?n_blocks ?(block_size=4096) ?polling_timeout ?fal
|
|||||||
Unix.close fd
|
Unix.close fd
|
||||||
);
|
);
|
||||||
Log.debug (fun f -> f "Monitoring eventfd %a" FD.pp st.eventfd);
|
Log.debug (fun f -> f "Monitoring eventfd %a" FD.pp st.eventfd);
|
||||||
|
result := Some (
|
||||||
Fiber.first
|
Fiber.first
|
||||||
(fun () -> main stdenv)
|
(fun () -> main stdenv)
|
||||||
(fun () -> monitor_event_fd st)
|
(fun () -> monitor_event_fd st)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
in
|
in
|
||||||
Log.debug (fun l -> l "exit")
|
Log.debug (fun l -> l "exit");
|
||||||
|
Option.get !result
|
||||||
|
@ -84,8 +84,8 @@ val run :
|
|||||||
?n_blocks:int ->
|
?n_blocks:int ->
|
||||||
?block_size:int ->
|
?block_size:int ->
|
||||||
?polling_timeout:int ->
|
?polling_timeout:int ->
|
||||||
?fallback:([`Msg of string] -> unit) ->
|
?fallback:([`Msg of string] -> 'a) ->
|
||||||
(stdenv -> unit) -> unit
|
(stdenv -> 'a) -> 'a
|
||||||
(** Run an event loop using io_uring.
|
(** Run an event loop using io_uring.
|
||||||
|
|
||||||
Uses {!Uring.create} to create the io_uring,
|
Uses {!Uring.create} to create the io_uring,
|
||||||
|
@ -813,7 +813,7 @@ let rec wakeup ~async run_q =
|
|||||||
Luv.Async.send async |> or_raise
|
Luv.Async.send async |> or_raise
|
||||||
| None -> ()
|
| None -> ()
|
||||||
|
|
||||||
let rec run main =
|
let rec run : type a. (_ -> a) -> a = fun main ->
|
||||||
Log.debug (fun l -> l "starting run");
|
Log.debug (fun l -> l "starting run");
|
||||||
let loop = Luv.Loop.init () |> or_raise in
|
let loop = Luv.Loop.init () |> or_raise in
|
||||||
let run_q = Lf_queue.create () in
|
let run_q = Lf_queue.create () in
|
||||||
@ -908,7 +908,7 @@ let rec run main =
|
|||||||
let new_fiber = Fiber_context.make_root () in
|
let new_fiber = Fiber_context.make_root () in
|
||||||
fork ~new_fiber (fun () ->
|
fork ~new_fiber (fun () ->
|
||||||
begin match main stdenv with
|
begin match main stdenv with
|
||||||
| () -> main_status := `Done
|
| v -> main_status := `Done v
|
||||||
| exception ex -> main_status := `Ex (ex, Printexc.get_raw_backtrace ())
|
| exception ex -> main_status := `Ex (ex, Printexc.get_raw_backtrace ())
|
||||||
end;
|
end;
|
||||||
Luv.Loop.stop loop
|
Luv.Loop.stop loop
|
||||||
@ -917,6 +917,6 @@ let rec run main =
|
|||||||
Lf_queue.close st.run_q;
|
Lf_queue.close st.run_q;
|
||||||
Luv.Handle.close async (fun () -> Luv.Loop.close loop |> or_raise);
|
Luv.Handle.close async (fun () -> Luv.Loop.close loop |> or_raise);
|
||||||
match !main_status with
|
match !main_status with
|
||||||
| `Done -> ()
|
| `Done v -> v
|
||||||
| `Ex (ex, bt) -> Printexc.raise_with_backtrace ex bt
|
| `Ex (ex, bt) -> Printexc.raise_with_backtrace ex bt
|
||||||
| `Running -> failwith "Deadlock detected: no events scheduled but main function hasn't returned"
|
| `Running -> failwith "Deadlock detected: no events scheduled but main function hasn't returned"
|
||||||
|
@ -122,4 +122,4 @@ val get_fd_opt : #Eio.Generic.t -> Low_level.File.t option
|
|||||||
|
|
||||||
(** {1 Main Loop} *)
|
(** {1 Main Loop} *)
|
||||||
|
|
||||||
val run : (stdenv -> unit) -> unit
|
val run : (stdenv -> 'a) -> 'a
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(** Select a suitable event loop for Eio. *)
|
(** Select a suitable event loop for Eio. *)
|
||||||
|
|
||||||
val run : (Eio.Stdenv.t -> unit) -> unit
|
val run : (Eio.Stdenv.t -> 'a) -> 'a
|
||||||
(** [run fn] runs an event loop and then calls [fn env] within it.
|
(** [run fn] runs an event loop and then calls [fn env] within it.
|
||||||
|
|
||||||
[env] provides access to the process's environment (file-system, network, etc).
|
[env] provides access to the process's environment (file-system, network, etc).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user