In the failure case the new value of [Head]{} is assigned to the “local copy” of [Head]{} (i.e., [Head’OLD]{}) via relaxed memory order. “Relaxed” is enough because RMW semantics will detect if the value of [Head]{} has been changed by a different thread anyway. The same applies to “Relaxed” in Line \[lfs:new\].

Implementation of entry [Pop]{} (lines \[lfs:popb\]–\[lfs:pope\]) follows along the same lines.

Memory management needs special consideration: In our case it is enough to use a [synchronized]{} counter that counts the number of threads inside [Pop]{}. If the counter equals $1$, memory can be freed. Ada’s storage pools are a perfect means for doing this without spoiling the code.

This example also shows how easy it is to migrate from a (working) blocking to a (working) non-blocking implementation of a program. Assume that a working implementation with a protected object exists, then one has to follow these steps:

1.  Replace keyword [protected]{} by keyword [concurrent]{}.

2.  Replace protected operations by DRF [concurrent]{} operations, thereby adding appropriate guards to the [concurrent]{} entries.

3.  Test the non-blocking program which now has default memory order.

4.  Carefully relax the memory ordering requirements: Add memory order aspects and/or attributes [Acquire]{}, [Release]{}, and/or [Relaxed]{} 