Proofs: Diffracting tree
These are the human proofs of Diffracting tree, at full length.
The diffracting tree is a quiescently consistent, lock-free counter full
This proof shows: correctness, quiescent-consistency, progress.
We use the pseudocode of the page, with width and balancers. Every read, write, compare-and-swap (CAS) and fetch-and-add on one word is atomic. Concurrent callers have distinct ids, and each thread runs at most one call at a time. A token is one call of GET-AND-INCREMENT.
Lemma 1 (the exchanger pairs symmetrically). If an exchange by token on slot returns TIMEOUT, then is a token whose concurrent exchange on returned . An exchange that returns TIMEOUT is not returned by any other exchange.
Proof. Look at the writes to . From EMPTY, only a CAS at line L14 by some changes it, to . From , only two CASes can succeed: 's own CAS at line L16, which expects its own id and sets EMPTY, or a CAS at line L18 by some , which sets , and then returns . From , no CAS of the code succeeds, since each expects EMPTY or WAITING, and the only plain writes are those of at lines L15 and L17. While waits after its successful line L14, it is the only thread that writes other than through line L18. So if 's CAS succeeds, 's CAS at line L16 fails, reads at line L15 or line L17, returns , and sets to EMPTY. If no such CAS by succeeds, 's CAS at line L16 succeeds and returns TIMEOUT, and nobody returned . A token that returns at line L18 was paired with the waiting in the same way, so the pairing is a matching on tokens.
Lemma 2 (one balancer). For a balancer , let and be the numbers of tokens that have returned side 0 and side 1 from BALANCE on . At any moment when no token is inside BALANCE on , . If tokens have entered and left, and .
Proof. A token leaves either at line L9 or at line L11. By Lemma 1, the tokens that leave at line L9 come in pairs that met in a slot of . When no token is inside BALANCE on , both members of each pair have left, and since the ids differ, one of them took side 0 and the other side 1. So diffracted tokens add the same amount to and . A token leaves at line L11 with the value that its successful CAS changed to . Successful CASes on are totally ordered, each flips the bit, and the bit starts at 0, so the values returned are in this order. After successful CASes, side 0 got of them and side 1 got . Adding the pairs gives , and with the two counts are and .
Lemma 3 (the step property of the tree). In a quiescent state in which tokens have entered the tree, wire has received tokens, for .
Proof. In a quiescent state every token that entered a balancer has left it, so the tokens that enter a child are exactly the tokens that left its parent on that side. Induction on . For the tree is one balancer, and Lemma 2 gives and . For , the root sends tokens to the subtree of side 0 and to the subtree of side 1. Both subtrees are diffracting trees of width , and the root has fixed bit 0 of the wire: wire of subtree is wire of the tree. By induction, wire gets tokens. Since and for each integer , this is . In the same way , and wire gets .
Lemma 4 (values in a quiescent state). In a quiescent state in which tokens have entered, the tokens have returned exactly the values , each once.
Proof. Wire 's counter was incremented by each of its tokens, by fetch-and-add, so they got and returned . A number is for exactly one pair, and , and holds exactly when . So the values returned are , each once.
Theorem (quiescent consistency). Each history of the diffracting tree is quiescently consistent with respect to the sequential counter.
Proof. First complete . Extend the execution by letting only the pending calls take steps, in any fair order, and start no new call. By the theorem on progress below, and since only finitely many calls are left, they all return, and the extended history is with responses appended for its pending calls, a completion of that ends in a quiescent state. Let be the quiescent points of , with at the end, and let be the number of calls that returned before . By Lemma 4 the calls that returned before got exactly the values , so the calls between and got exactly . Let list the calls of each segment in the order of their values, and the segments in order. is a legal sequential counter history with the same results as , and if a quiescent point separates calls and , is in an earlier segment and precedes in .
Theorem (lock-freedom). In every infinite execution in which some call is pending, infinitely many calls return.
Proof. Suppose that from some moment on no call returns. Each call passes balancers. In a balancer, the prism part (lines L7 to L9, with lines L12 to L19) ends within own steps, and the fetch-and-add at line L5 is one step. So some thread must run the loop of line L10 for ever. Each turn of that loop that fails means that the toggle changed between its read and its CAS, which needs a successful CAS by another token, and each successful CAS ends that token's BALANCE on that balancer. No thread starts a new call before its current call returns, so at most calls are active, each with at most successful CASes. So after some moment no CAS at line L10 succeeds. Then no toggle changes, and the next CAS of a thread in the loop of line L10 succeeds. This contradicts the assumption.