forked from microsoft/verona
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathverona_rc_wrc.cvf
executable file
·162 lines (141 loc) · 4.03 KB
/
verona_rc_wrc.cvf
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* Atomic reference counter from Verona
*
* Strong and Weak references
*
* Provides a wait-free acquire_strong_from_weak.
*
* This was verified using ff235a5a5e0e4057 from Matt Windsor's development
* branch of Starling.
* https://github.com/MattWindsor91/starling-tool
*
* Caveats: The proof does not contain the full lifetime management aspects
* such as actually running the destructor of a Cown, or deallocating the
* underlying representation.
*/
/**
* The strong reference count
*/
shared int rc;
/*
* The weak reference count
*/
shared int wrc;
/**
* This is a mark bit added to the reference count.
*/
shared bool closed;
thread bool success;
thread bool lost_weak;
thread bool last;
thread bool more_work;
view iter StrongRef;
view iter WeakRef;
view NoStrong;
view NoWeak;
/**
* This corresponds to Object::incref in object.h
*/
method acquire_strong()
{
{| StrongRef |} <| rc++; |> {| StrongRef * StrongRef |}
}
/**
* This corresponds to Cown::weak_acquire in cown.h
*/
method acquire_weak()
{
{| WeakRef |} <| wrc++; |> {| WeakRef * WeakRef |}
}
/**
* This corresponds to Cown::weak_acquire in cown.h
* It is the same method as above, just with a different specification.
*/
method acquire_weak_from_strong()
{
{| StrongRef |} <| wrc++; |> {| StrongRef * WeakRef |}
}
/*
This has two returns last and more_work
If last is true, then this was decremented the final strong reference count
If more_work is true, then the process of release this reference count resulted in
and additional weak reference that the caller must remove.
This corresponds to Object::decref_cown in object.h
*/
method release_strong()
{
{| StrongRef |}
<| rc--; last = rc==0; |>
{| if last { WeakRef } |}
if last {
{| WeakRef * if !last { false} |}
// The following is a CAS to attempt to set the bit if the
// rc is still zero.
<| last = ((closed == false) && (rc == 0)); if last {closed = true;} |>
{| WeakRef * if last { NoStrong } |}
more_work = !last;
{| if last { NoStrong * WeakRef }
* if more_work { WeakRef } |}
}
else
{
{| if last { NoStrong * WeakRef } |}
more_work = false;
{| if last { NoStrong * WeakRef }
* if more_work { WeakRef } |}
}
{| if last { NoStrong * WeakRef }
* if more_work { WeakRef } |}
}
/**
* This is corresponds to the start of
* Cown::weak_release in cown.h
* The function in Verona also handles the deallocation of
* the underlying object, and integrating with other considerations
* of the runtime.
*/
method release_weak()
{
{| WeakRef |}
<| wrc--; last = wrc == 0; |>
{| if last { NoWeak } |}
}
/**
This has two returns
success signifies we successfully acquired a StrongRef
lost_weak signifies we lost our weak reference in the acquisition.
This corresponds to Object::acquire_strong_from_weak in object.h
*/
method acquire_strong_from_weak()
{
{| WeakRef |}
<|
lost_weak = rc == 0 && !closed;
rc++;
success = !closed;
|>
{| if (success) { StrongRef }
* if (lost_weak) { emp } else {WeakRef}
|}
}
// Invariant
constraint emp ->
rc >= 0 &&
wrc >= 0 &&
(rc > 0 => (wrc > 0 || closed == true));
// Permission to run the destructor
constraint NoStrong -> closed == true;
// Permission to deallocate the underlying representation
// Would be good to prove that the rc is `closed` but that is
// not currently part of this proof.
constraint NoWeak -> wrc == 0;
// Linear
constraint NoStrong * NoStrong -> false;
constraint NoWeak * NoWeak -> false;
// Starling complains about the following.
// It is trivially true from the definitions of NoWeak and WeakRef.
//constraint NoWeak * WeakRef -> false;
constraint iter[n] StrongRef -> n > 0 => (rc >= n && closed == false);
constraint iter[n] WeakRef ->
n > 0
=> ((closed == false && rc > 0 && wrc >= n + 1 )
|| ((closed == true || rc == 0) && wrc >= n ));