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