forked from bcpierce00/unison
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlwt_util.ml
88 lines (75 loc) · 2.04 KB
/
lwt_util.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
open Lwt
let rec iter f l =
let l = List.fold_left (fun acc a -> f a :: acc) [] l in
let l = List.rev l in
List.fold_left (fun rt t -> t >>= fun () -> rt) (Lwt.return ()) l
let rec map f l =
match l with
[] ->
return []
| v :: r ->
let t = f v in
let rt = map f r in
t >>= (fun v' ->
rt >>= (fun l' ->
return (v' :: l')))
let map_with_waiting_action f wa l =
let rec loop l =
match l with
[] ->
return []
| v :: r ->
let t = f v in
let rt = loop r in
t >>= (fun v' ->
(* Perform the specified "waiting action" for the next *)
(* item in the list. *)
if r <> [] then
wa (List.hd r)
else
();
rt >>= (fun l' ->
return (v' :: l')))
in
if l <> [] then
wa (List.hd l)
else
();
loop l
let rec map_serial f l =
match l with
[] ->
return []
| v :: r ->
f v >>= (fun v' ->
map_serial f r >>= (fun l' ->
return (v' :: l')))
let join l = iter (fun x -> x) l
type region =
{ mutable size : int;
mutable count : int;
waiters : (unit Lwt.t * int) Queue.t }
let make_region count = { size = count; count = 0; waiters = Queue.create () }
let resize_region reg sz = reg.size <- sz
let purge_region reg = Queue.clear reg.waiters
let leave_region reg sz =
try
if reg.count - sz >= reg.size then raise Queue.Empty;
let (w, sz') = Queue.take reg.waiters in
reg.count <- reg.count - sz + sz';
Lwt.wakeup w ()
with Queue.Empty ->
reg.count <- reg.count - sz
let run_in_region_1 reg sz thr =
(catch
(fun () -> thr () >>= (fun v -> leave_region reg sz; return v))
(fun e -> leave_region reg sz; fail e))
let run_in_region reg sz thr =
if reg.count >= reg.size then begin
let res = wait () in
Queue.add (res, sz) reg.waiters;
res >>= (fun () -> run_in_region_1 reg sz thr)
end else begin
reg.count <- reg.count + sz;
run_in_region_1 reg sz thr
end