C.6.2 The Package System.Atomic_Operations.Exchange
{
AI12-0234-1}
The language-defined generic package System.Atomic_Operations.Exchange
provides the following operations:
To atomically compare the
value of two atomic objects, and update the first atomic object with
a desired value if both objects were found to be equal, or otherwise
update the second object with the value of the first object.
To atomically update the
value of an atomic object, and then return the value that the atomic
object had just prior to the update.
Static Semantics
{
AI12-0234-1}
The generic library package System.Atomic_Operations.Exchange
has the following declaration:
generic
type Atomic_Type is private with Atomic;
package System.Atomic_Operations.Exchange
with Pure, Nonblocking is
function Atomic_Exchange (Item : aliased in out Atomic_Type;
Value : Atomic_Type) return Atomic_Type
with Convention => Intrinsic;
function Atomic_Compare_And_Exchange
(Item : aliased in out Atomic_Type;
Prior : aliased in out Atomic_Type;
Desired : Atomic_Type) return Boolean
with Convention => Intrinsic;
function Is_Lock_Free (Item : aliased Atomic_Type) return Boolean
with Convention => Intrinsic;
end System.Atomic_Operations.Exchange;
{
AI12-0234-1}
Atomic_Exchange atomically assigns the value of
Value to Item, and returns the previous value of Item.
{
AI12-0234-1}
Atomic_Compare_And_Exchange first evaluates the
value of Prior. Atomic_Compare_And_Exchange then performs the following
steps as part of a single indivisible operation:
evaluates the value of Item;
compares the value of Item
with the value of Prior;
if equal, assigns Item the
value of Desired;
otherwise, makes no change
to the value of Item.
{
AI12-0234-1}
After these steps, if the value of Item and Prior
did not match, Prior is assigned the original value of Item, and the
function returns False. Otherwise, Prior is unaffected and the function
returns True.
Examples
{
AI12-0234-1}
Example of a spin lock using Atomic_Exchange:
type Atomic_Boolean is new Boolean with Atomic;
package Exchange is new
Atomic_Operations.Exchange (Atomic_Type => Atomic_Boolean);
Lock : aliased Atomic_Boolean := False;
...
begin -- Some critical section, trying to get the lock:
-- Obtain the lock
while Exchange.Atomic_Exchange (Item => Lock, Value => True) loop
null;
end loop;
... -- Do stuff
Lock := False; -- Release the lock
end;
Extensions to Ada 2012
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe