@@ -10,9 +10,26 @@ ASSUME Assumption ==
1010 /\ Consumers # { } (* at least one consumer *)
1111 /\ Producers \intersect Consumers = { } (* no thread is both consumer and producer *)
1212 /\ BufCapacity \in ( Nat \ { 0 } ) (* buffer capacity is at least 1 *)
13+ -----------------------------------------------------------------------------
14+ \* These three variables are pratically constants but have to be VARIABLES because TLC
15+ \* doesn't support verification of sets of CONSTANT values.
16+ \* (see https://github.com/tlaplus/tlaplus/issues/272)
17+ VARIABLES B , P , C
18+ consts == << B , P , C >>
19+
20+ (* ASSUME *) Constant ==
21+ /\ B \in 1 .. BufCapacity
22+ /\ P \in SUBSET Producers
23+ /\ C \in SUBSET Consumers
24+ /\ [] [ B = B ' /\ P = P ' /\ C = C ' ]_ consts
25+
26+ ConstInit ==
27+ /\ B \in 1 .. BufCapacity
28+ /\ P \in ( SUBSET Producers \ { { } } )
29+ /\ C \in ( SUBSET Consumers \ { { } } )
1330
1431VARIABLES buffer , waitSet , prod , cons
15- vars == << buffer , waitSet , prod , cons >>
32+ vars == << B , P , C , buffer , waitSet , prod , cons >>
1633
1734-----------------------------------------------------------------------------
1835
@@ -32,10 +49,10 @@ Poison == CHOOSE v : TRUE
3249Put ( t , d ) ==
3350 /\ UNCHANGED << prod , cons >>
3451 /\ t \notin waitSet
35- /\ \/ /\ Len ( buffer ) < BufCapacity
52+ /\ \/ /\ Len ( buffer ) < B
3653 /\ buffer ' = Append ( buffer , d )
3754 /\ NotifyOther ( t )
38- \/ /\ Len ( buffer ) = BufCapacity
55+ \/ /\ Len ( buffer ) = B
3956 /\ Wait ( t )
4057
4158Get ( t ) ==
@@ -81,18 +98,20 @@ Cleanup ==
8198 \* Make one of the producers the janitor that cleans up (we always
8299 \* choose the same janitor). An implementation may simply create a fresh
83100 \* process/thread (here it would be a nuisance because of TypeInv...).
84- /\ Put ( CHOOSE p \in Producers : TRUE , Poison )
101+ /\ Put ( CHOOSE p \in P : TRUE , Poison )
85102
86103-----------------------------------------------------------------------------
87104
88105(* Initially, the buffer is empty and no thread is waiting. *)
89- Init == /\ prod = Producers
90- /\ cons = Consumers
106+ Init == /\ ConstInit
107+ /\ prod = P
108+ /\ cons = C
91109 /\ buffer = << >>
92110 /\ waitSet = { }
93111
94112(* Then, pick a thread out of all running threads and have it do its thing. *)
95113Next ==
114+ /\ UNCHANGED consts
96115 /\ \/ \E p \in prod : Put ( p , p )
97116 \/ \E p \in prod : Terminate ( p )
98117 \/ \E c \in cons : Get ( c )
@@ -102,11 +121,11 @@ Next ==
102121
103122(* TLA+ is untyped, thus lets verify the range of some values in each state. *)
104123TypeInv ==
105- /\ buffer \in Seq ( Producers \cup { Poison } )
124+ /\ buffer \in Seq ( P \cup { Poison } )
106125 /\ Len ( buffer ) \in 0 .. BufCapacity
107- /\ waitSet \in SUBSET ( Consumers \cup Producers )
108- /\ prod \in SUBSET Producers
109- /\ cons \in SUBSET Consumers
126+ /\ waitSet \in SUBSET ( C \cup P )
127+ /\ prod \in SUBSET P
128+ /\ cons \in SUBSET C
110129
111130(* No Deadlock *)
112131NoDeadlock == waitSet # ( Producers \cup Consumers )
0 commit comments