Skip to content

Commit cc05e2b

Browse files
Merge pull request #960 from kit-ty-kate/run_in_main_no_wait
Add Lwt_preemptive.run_in_main_no_wait
2 parents a8122b7 + bbafaf3 commit cc05e2b

File tree

4 files changed

+71
-6
lines changed

4 files changed

+71
-6
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
* Lwt.reraise an exception raising function which preserves backtraces, recommended for use in Lwt.catch (#963)
2222
* Expose Lwt_io.delete_recursively for deleting a directory and its content recursively. (#984, Antonin Décimo)
2323

24+
* Lwt_preemptive.run_in_main_dont_wait to run a function in the main preemptive thread but without waiting for the result. (Kate Deplaix, #960)
25+
2426
====== Build ======
2527

2628
* Remove unused dependency in dune file. (#969, Kate Deplaix)

src/unix/lwt_preemptive.ml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@ let job_notification =
228228
Mutex.unlock jobs_mutex;
229229
ignore (thunk ()))
230230

231+
let run_in_main_dont_wait f =
232+
(* Add the job to the queue. *)
233+
Mutex.lock jobs_mutex;
234+
Queue.add f jobs;
235+
Mutex.unlock jobs_mutex;
236+
(* Notify the main thread. *)
237+
Lwt_unix.send_notification job_notification
238+
231239
(* There is a potential performance issue from creating a cell every time this
232240
function is called. See:
233241
https://github.com/ocsigen/lwt/issues/218
@@ -245,13 +253,13 @@ let run_in_main f =
245253
CELL.set cell result;
246254
Lwt.return_unit
247255
in
248-
(* Add the job to the queue. *)
249-
Mutex.lock jobs_mutex;
250-
Queue.add job jobs;
251-
Mutex.unlock jobs_mutex;
252-
(* Notify the main thread. *)
253-
Lwt_unix.send_notification job_notification;
256+
run_in_main_dont_wait job;
254257
(* Wait for the result. *)
255258
match CELL.get cell with
256259
| Result.Ok ret -> ret
257260
| Result.Error exn -> raise exn
261+
262+
(* This version shadows the one above, adding an exception handler *)
263+
let run_in_main_dont_wait f handler =
264+
let f () = Lwt.catch f (fun exc -> handler exc; Lwt.return_unit) in
265+
run_in_main_dont_wait f

src/unix/lwt_preemptive.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ val run_in_main : (unit -> 'a Lwt.t) -> 'a
3434
retrieve values set this way inside [f ()], but not values set using
3535
{!Lwt.with_value} outside [f ()]. *)
3636

37+
val run_in_main_dont_wait : (unit -> unit Lwt.t) -> (exn -> unit) -> unit
38+
(** [run_in_main_dont_wait f h] does the same as [run_in_main f] but a bit faster
39+
and lighter as it does not wait for the result of [f].
40+
41+
If [f]'s promise is rejected (or if it raises), then the function [h] is
42+
called with the rejection exception.
43+
44+
@since 5.7.0 *)
45+
3746
val init : int -> int -> (string -> unit) -> unit
3847
(** [init min max log] initialises this module. i.e. it launches the
3948
minimum number of preemptive threads and starts the {b

test/unix/test_lwt_unix.ml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,52 @@ let lwt_preemptive_tests = [
10631063
Lwt_preemptive.detach f () >>= fun x ->
10641064
Lwt.return (x = 42)
10651065
end;
1066+
test "run_in_main_dont_wait" begin fun () ->
1067+
let p, r = Lwt.wait () in
1068+
let f () =
1069+
Lwt_preemptive.run_in_main_dont_wait
1070+
(fun () ->
1071+
Lwt.pause () >>= fun () ->
1072+
Lwt.pause () >>= fun () ->
1073+
Lwt.wakeup r 42;
1074+
Lwt.return ())
1075+
(fun _ -> assert false)
1076+
in
1077+
Lwt_preemptive.detach f () >>= fun () ->
1078+
p >>= fun x ->
1079+
Lwt.return (x = 42)
1080+
end;
1081+
test "run_in_main_dont_wait_fail" begin fun () ->
1082+
let p, r = Lwt.wait () in
1083+
let f () =
1084+
Lwt_preemptive.run_in_main_dont_wait
1085+
(fun () ->
1086+
Lwt.pause () >>= fun () ->
1087+
Lwt.pause () >>= fun () ->
1088+
raise Exit)
1089+
(function Exit -> Lwt.wakeup r 45 | _ -> assert false)
1090+
in
1091+
Lwt_preemptive.detach f () >>= fun () ->
1092+
p >>= fun x ->
1093+
Lwt.return (x = 45)
1094+
end;
1095+
test "run_in_main_with_dont_wait" begin fun () ->
1096+
let p, r = Lwt.wait () in
1097+
let f () =
1098+
Lwt_preemptive.run_in_main (fun () ->
1099+
Lwt.dont_wait
1100+
(fun () ->
1101+
Lwt.pause () >>= fun () ->
1102+
Lwt.pause () >>= fun () ->
1103+
Lwt.wakeup r 42;
1104+
Lwt.return ())
1105+
(function _ -> Stdlib.exit 2);
1106+
Lwt.return ())
1107+
in
1108+
Lwt_preemptive.detach f () >>= fun () ->
1109+
p >>= fun x ->
1110+
Lwt.return (x = 42)
1111+
end;
10661112
]
10671113

10681114
let getlogin_works =

0 commit comments

Comments
 (0)