C.6.2 The Package System.Atomic_Operations.Exchange
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
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;
Atomic_Exchange atomically assigns the value of Value
to Item, and returns the previous value of Item.
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.
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
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;
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe