Справочник по Ada 2005
9.4 Защищённые блоки и защищённые объекты
Защищённый объект предоставляет координированный доступ к общим данным через вызовы видимых защищённых операций, которые могут быть защищёнными подпрограммами или защищёнными входами. Защищённый блок объявляется защищённым объявлением, которое имеет соответствующий protected_body. Защищённое объявление может быть protected_type_declaration, в этом случае оно объявляет именованный защищённый тип; иначе, оно может быть single_protected_declaration, в этом случае оно определяет анонимный защищённый тип, а также объявляет именованный защищённый объект этого типа.
Синтаксис
protected_type_declaration ::=
protected type defining_identifier [known_discriminant_part] is
[new interface_list with]
protected_definition;
protected type defining_identifier [known_discriminant_part] is
[new interface_list with]
protected_definition;
single_protected_declaration ::=
protected defining_identifier is
[new interface_list with]
protected_definition;
protected defining_identifier is
[new interface_list with]
protected_definition;
protected_definition ::=
{ protected_operation_declaration }
[ private
{ protected_element_declaration } ]
end [protected_identifier]
{ protected_operation_declaration }
[ private
{ protected_element_declaration } ]
end [protected_identifier]
protected_body ::=
protected body defining_identifier is
{ protected_operation_item }
end [protected_identifier];
protected body defining_identifier is
{ protected_operation_item }
end [protected_identifier];
Если protected_identifier появляется в конце protected_definition или protected_body, он должен повторять defining_identifier.
Правила законности
Этот абзац был удалён.
Статическая семантика
protected_definition определяет защищённый тип и его первый подтип. Список protected_operation_declaration в protected_definition, вместе с known_discriminant_part, если таковой имеется, называется видимой частью защищённого блока. Необязательный список protected_element_declaration после ключевого слова private называется скрытой частью защищённого блока.
Для защищённого объявления с interface_list, защищённый тип наследует пользовательские примитивные подпрограммы от каждого родительского типа (см. 3.9.4), так же, как производный тип наследует пользовательские примитивные подпрограммы от своих родительских типов (см. 3.4). Если первый параметр унаследованной примитивной подпрограммы является защищённым типом или параметром доступа, обозначающим защищённый тип, и существует protected_operation_declaration для защищённой подпрограммы или отдельного входа с тем же идентификатором внутри защищённого объявления, профиль которого соответствует префиксу взгляда на профиль унаследованной подпрограммы, унаследованная подпрограмма считается реализованной соответствующей защищённой подпрограммой или входом.
Правила законности
Защищённое объявление требует завершения, которое должно быть protected_body, и каждый protected_body должен быть завершением некоторого защищённого объявления.
Каждый interface_subtype_mark из interface_list, появляющийся в защищённом объявлении, должен обозначать ограниченный интерфейсный тип, который не является интерфейсом задачи.
Префиксный профиль взгляда явно объявленной примитивной подпрограммы помеченного защищённого типа не должен соответствовать типу никакой защищённой операции защищённого типа, если первый параметр подпрограммы является защищённым типом или параметром доступа, обозначающим защищённый тип.
Для каждой примитивной подпрограммы, унаследованной типом, объявленным защищённым объявлением, максимум одно из следующего должно быть применимо:
- Унаследованная подпрограмма переопределена примитивной подпрограммой защищённого типа, в этом случае переопределяющая подпрограмма должна соответствовать типу унаследованной подпрограммы и не должна быть абстрактной; или
- Унаследованная подпрограмма реализована защищённой подпрограммой или отдельным входом защищённого типа, в этом случае её префиксный профиль взгляда должен соответствовать типу защищённой подпрограммы или входа.
Если ни одно из вышеперечисленного не применимо, унаследованная подпрограмма должна быть пустой процедурой. В дополнение к местам, где обычно применяются правила законности (см. 12.3), эти правила также применяются в частях экземпляра обобщённого блока.
Если унаследованная подпрограмма реализована защищённой процедурой или входом, то первый параметр унаследованной подпрограммы должен быть режима out или in out, или параметром доступа к переменной.
Если у защищённого объявления подпрограммы есть overriding_indicator, то на момент объявления:
- если overriding_indicator — overriding, то подпрограмма должна реализовывать унаследованную подпрограмму;
- если overriding_indicator — not overriding, то подпрограмма не должна реализовывать никакую унаследованную подпрограмму.
В дополнение к местам, где обычно применяются правила законности (см. 12.3), эти правила также применяются в частях экземпляра обобщённого блока.
Динамическая семантика
Выполнение защищённого объявления выполняет protected_definition. Выполнение single_protected_declaration также создаёт объект (анонимного) защищённого типа.
Выполнение protected_definition создаёт защищённый тип и его первый подтип; оно также включает выполнение component_declaration и protected_operation_declaration в заданном порядке.
В рамках инициализации защищённого объекта выполняются все ограничения объекта (см. 3.8).
Выполнение protected_body не имеет иных последствий, кроме установления того, что защищённые операции типа могут быть вызваны без сбоя Elaboration_Check.
Содержимое объекта данного защищённого типа включает:
- Значения компонентов защищённого объекта, включая (неявно) очередь входа для каждого входа, объявленного для защищённого объекта;
- Представление состояния ресурса выполнения, связанного с защищенным объектом (такой ресурс связан с каждым защищенным объектом).
Ресурс выполнения, связанный с защищенным объектом, должен быть получен для чтения или обновления любых компонентов защищенного объекта; он может быть получен (как часть защищенного действия — см. 9.5.1) либо для одновременного только-для-чтения доступа, либо для исключительного чтении-записи доступа.
В качестве первой стадии завершения защищенного объекта, каждый оставшийся вызов в очереди входа объекта удаляется из очереди, и в месте соответствующего entry_call_statement генерируется ошибка Program_Error.
Ограниченные (времени выполнения) ошибки
Вызов входа или подпрограммы защищенного объекта после завершения этого объекта является ограниченной ошибкой. Если ошибка обнаружена, генерируется ошибка Program_Error. В противном случае вызов выполняется нормально, что может привести к вечному ожиданию задачи в очереди.
ПРИМЕЧАНИЯ
13 Внутри объявления или тела защищенного блока, кроме access_definition, имя защищенного блока обозначает текущую инстанцию блока (см. 8.6), а не первый подтип соответствующего защищенного типа (и, следовательно, имя не может быть использовано как subtype_mark).
14 selected_component может быть использован для обозначения дискриминанта защищенного объекта (см. 4.1.3). Внутри защищенного блока имя дискриминанта защищенного типа обозначает соответствующий дискриминант текущей инстанции блока.
15 Защищенный тип является ограниченным типом (см. 7.5), и поэтому исключает использование assignment_statement и предопределённых операторов равенства.
16 Тела защищенных операций, заданные в protected_body, определяют действия, которые происходят при вызовах защищенных операций.
17 Объявления в частной части видимы только внутри частной части и тела защищенного блока.
Примеры
Пример объявления защищенного типа и соответствующего тела:
protected type Resource is
entry Seize;
procedure Release;
private
Busy : Boolean := False;
end Resource;
entry Seize;
procedure Release;
private
Busy : Boolean := False;
end Resource;
protected body Resource is
entry Seize when not Busy is
begin
Busy := True;
end Seize;
entry Seize when not Busy is
begin
Busy := True;
end Seize;
procedure Release is
begin
Busy := False;
end Release;
end Resource;
begin
Busy := False;
end Release;
end Resource;
Пример одиночного защищенного объявления и соответствующего тела:
protected Shared_Array is
-- Index, Item, and Item_Array are global types
function Component (N : in Index) return Item;
procedure Set_Component(N : in Index; E : in Item);
private
Table : Item_Array(Index) := (others => Null_Item);
end Shared_Array;
-- Index, Item, and Item_Array are global types
function Component (N : in Index) return Item;
procedure Set_Component(N : in Index; E : in Item);
private
Table : Item_Array(Index) := (others => Null_Item);
end Shared_Array;
protected body Shared_Array is
function Component(N : in Index) return Item is
begin
return Table(N);
end Component;
function Component(N : in Index) return Item is
begin
return Table(N);
end Component;
procedure Set_Component(N : in Index; E : in Item) is
begin
Table(N) := E;
end Set_Component;
end Shared_Array;
begin
Table(N) := E;
end Set_Component;
end Shared_Array;
Примеры защищенных объектов:
Control : Resource;
Flags : array(1 .. 100) of Resource;
Flags : array(1 .. 100) of Resource;