Skip to content

Commit 6faa0c5

Browse files
raphael-proustrr0gi
authored andcommitted
Lwt_util.idle_check
1 parent d890d2f commit 6faa0c5

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
(executable
7070
(name test)
71-
(libraries devkit extlib extunix libevent ocamlnet_lite ounit2 unix yojson)
71+
(libraries lwt lwt.unix devkit extlib extunix libevent ocamlnet_lite ounit2 unix yojson)
7272
(modules test test_httpev))
7373

7474
; uses 8GB+ RAM, so do not run as part of test suite

lwt_util.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,17 @@ let action name f x =
6060
let action_do name f = action name f ()
6161

6262
let async f = Lwt.async Daemon.(fun () -> try%lwt unless_exit (f ()) with ShouldExit -> Lwt.return_unit)
63+
64+
let idle_check ~interval =
65+
let timestamp = ref (Time.now ()) in
66+
let stamp () = timestamp := Time.now () in
67+
let rec wait () =
68+
let idle = Time.ago !timestamp in
69+
if idle > interval then
70+
Lwt.return_unit
71+
else begin
72+
let%lwt () = Lwt_unix.sleep (interval -. idle) in
73+
wait ()
74+
end
75+
in
76+
(stamp, wait ())

lwt_util.mli

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,13 @@ val action_do : string -> (unit -> 'a Lwt.t) -> 'a Lwt.t
2222

2323
(** same as [Lwt.async] but also cancels task on {!Daemon.ShouldExit} *)
2424
val async : (unit -> unit Lwt.t) -> unit
25+
26+
(** [idle_check ~interval] is a pair [(stamp,wait)] where you use
27+
[stamp: unit -> unit] to indicate activity, and [wait : unit Lwt.t] is a
28+
promise that resolves if there's been no calls to [stamp] during an
29+
[interval].
30+
31+
This is typically used to manage a background task (e.g., periodically
32+
fetching data from a remote source) based on whether there is ongoing
33+
activity (e.g., whether the data is being used in the UI). *)
34+
val idle_check : interval:Time.duration -> ((unit -> unit) * unit Lwt.t)

test.ml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,35 @@ let () = test "Web.urlencode" @@ fun () ->
544544
assert_equal (Web.urlencode "Hello Günter") "Hello+G%C3%BCnter";
545545
()
546546

547+
let () =
548+
let open Lwt.Syntax in
549+
let rec pings f = function
550+
| [] -> Lwt.return_unit
551+
| t :: ts ->
552+
let* () = Lwt_unix.sleep t in
553+
f ();
554+
pings f ts
555+
in
556+
test "Lwt_util.idle_check" @@ fun () ->
557+
let accumulator = ref 0 in
558+
let (s, w) = Lwt_util.idle_check ~interval:0.01 in
559+
Lwt_main.run (
560+
Lwt.pick [
561+
pings (fun () -> incr accumulator; s ()) [0.001; 0.001; 0.001; 1.];
562+
w
563+
]
564+
);
565+
assert_equal !accumulator 3;
566+
let (s, w) = Lwt_util.idle_check ~interval:0.01 in
567+
Lwt_main.run (
568+
Lwt.pick [
569+
pings (fun () -> incr accumulator; s ()) [0.001; 1.];
570+
w
571+
]
572+
);
573+
assert_equal !accumulator 4;
574+
()
575+
547576
let tests () =
548577
let (_:test_results) = run_test_tt_main ("devkit" >::: List.rev !tests) in
549578
()

0 commit comments

Comments
 (0)