Source file order_managed_interval.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module O = Order_indir
type t = {
a : O.t;
b : O.t;
lock : gc_lock;
}
and gc_lock = {
mutable locks: int;
mutable forgotten: O.t list;
}
let lock lock =
lock.locks <- lock.locks + 1
let unlock lock =
lock.locks <- lock.locks - 1;
if lock.locks = 0 then
match lock.forgotten with
| [] -> ()
| forgotten ->
lock.forgotten <- [];
List.iter O.forget forgotten
let forget {lock; a; b} =
if lock.locks > 0 then
lock.forgotten <- a :: b :: lock.forgotten
else
(O.forget a; O.forget b)
let is_valid t =
lock t.lock;
let result = O.is_valid t.a in
unlock t.lock;
result
let root () =
let a = O.root () in
let b = O.after a in
let t = {a; b; lock = { locks = 0; forgotten = [] }} in
Gc.finalise forget t;
t
let after t =
lock t.lock;
let b = O.after t.b in
let a = O.before b in
let t' = {a; b; lock = t.lock} in
Gc.finalise forget t';
unlock t.lock;
t'
let before t =
lock t.lock;
let a = O.before t.a in
let b = O.after a in
let t' = {a; b; lock = t.lock} in
Gc.finalise forget t';
unlock t.lock;
t'
let inside t =
lock t.lock;
let a = O.after t.a in
let b = O.before t.b in
let t' = {a; b; lock = t.lock} in
Gc.finalise forget t';
unlock t.lock;
t'
let outside t =
lock t.lock;
let a = O.before t.a in
let b = O.after t.b in
let t' = {a; b; lock = t.lock} in
Gc.finalise forget t';
unlock t.lock;
t'
let same_order t1 t2 =
O.same_order t1.a t2.a
type rel =
| Before
| Inside
| Equal
| Outside
| After
let compare t1 t2 =
if t1 == t2 then Equal else
let ca = O.compare t1.a t2.a <= 0 in
let cb = O.compare t1.b t2.b <= 0 in
match ca, cb with
| true, true -> Before
| true, false -> Outside
| false, true -> Inside
| false, false -> After
let cardinal t =
O.cardinal t.a / 2
let unsafe_check t msg =
lock t.lock;
O.unsafe_check t.a ("(Order_managed_interval a) " ^ msg);
O.unsafe_check t.b ("(Order_managed_interval b) " ^ msg);
unlock t.lock