Справочник по Ada (Ada 2022)
C.6.2 Пакет System.Atomic_Operations.Exchange
Определяемый языком обобщённый пакет System.Atomic_Operations.Exchange предоставляет следующие операции:
- Атомно сравнить значения двух атомных объектов и обновить первый атомный объект желаемым значением, если оба объекта оказались равными, или в противном случае обновить второй объект значением первого объекта.
- Атомно обновить значение атомного объекта и вернуть значение, которое атомный объект имел непосредственно перед обновлением.
Статическая семантика
Обобщённый пакет библиотек System.Atomic_Operations.Exchange имеет следующее объявление:
generic
type Atomic_Type is private with Atomic;
package System.Atomic_Operations.Exchange
with Pure, Nonblocking is
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;
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;
(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;
with Convention => Intrinsic;
end System.Atomic_Operations.Exchange;
Atomic_Exchange атомно присваивает значение Value объекту Item и возвращает предыдущее значение Item.
Atomic_Compare_And_Exchange сначала вычисляет значение Prior. Затем Atomic_Compare_And_Exchange выполняет следующие шаги как часть единой неделимой операции:
- вычисляет значение Item;
- сравнивает значение Item со значением Prior;
- если они равны, присваивает Item значение Desired;
- в противном случае не изменяет значение Item.
После этих шагов, если значения Item и Prior не совпали, Prior присваивается исходное значение Item, а функция возвращает False. В противном случае Prior не изменяется, и функция возвращает True.
Примеры
Пример спин-блокировки с использованием Atomic_Exchange:
type Atomic_Boolean is new Boolean with Atomic;
package Exchange is new
Atomic_Operations.Exchange (Atomic_Type => Atomic_Boolean);
package Exchange is new
Atomic_Operations.Exchange (Atomic_Type => Atomic_Boolean);
Lock : aliased Atomic_Boolean := False;
...
begin -- Некоторая критическая секция, пытающаяся получить блокировку:
-- Получение блокировки
while Exchange.Atomic_Exchange (Item => Lock, Value => True) loop
null;
end loop;
while Exchange.Atomic_Exchange (Item => Lock, Value => True) loop
null;
end loop;
... -- Выполнение действий
Lock := False; -- Освобождение блокировки
end;
end;