Справочник Ada 2012
9.4 Защищённые блоки и защищённые объекты
Защищённый объект предоставляет согласованный доступ к общим данным через вызовы видимых защищённых операций, которые могут быть защищёнными подпрограммами или защищёнными входами. Защищённый блок объявляется защищённым объявлением, имеющим соответствующий protected_body. Защищённое объявление может быть protected_type_declaration, в этом случае оно объявляет именованный тип защищённого объекта; альтернативно, оно может быть single_protected_declaration, в этом случае оно определяет анонимный тип защищённого объекта, а также объявляет именованный защищённый объект этого типа.
Синтаксис
protected_type_declaration ::=
protected type defining_identifier [known_discriminant_part]
[aspect_specification] is
[new interface_list with]
protected_definition;
protected type defining_identifier [known_discriminant_part]
[aspect_specification] is
[new interface_list with]
protected_definition;
single_protected_declaration ::=
protected defining_identifier
[aspect_specification] is
[new interface_list with]
protected_definition;
protected defining_identifier
[aspect_specification] 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
[aspect_specification] is
{ protected_operation_item }
end [protected_identifier];
protected body defining_identifier
[aspect_specification] is
{ protected_operation_item }
end [protected_identifier];
protected_operation_item ::= subprogram_declaration
| subprogram_body
| null_procedure_declaration
| expression_function_declaration
| entry_body
| aspect_clause
| subprogram_body
| null_procedure_declaration
| expression_function_declaration
| entry_body
| aspect_clause
Если protected_identifier появляется в конце protected_definition или protected_body, он должен повторять defining_identifier.
Абзац 10 был удалён.
Статическая семантика
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, или параметр доступа к переменной. Если унаследованная подпрограмма реализуется защищённой функцией, то первый параметр унаследованной подпрограммы должен иметь режим in, но не быть параметром доступа к переменной.
Если объявление защищённой подпрограммы имеет overriding_indicator, то в момент объявления:
- если overriding_indicator это overriding, то подпрограмма должна реализовывать унаследованную подпрограмму;
- если overriding_indicator это not overriding, то подпрограмма не должна реализовывать ни одну унаследованную подпрограмму.
Помимо мест, где обычно применяются Правила допустимости (см. 12.3), эти правила также применяются в приватной части экземпляра генерируемого блока.
Динамическая семантика
Выполнение защищённого объявления выполняет protected_definition. Выполнение single_protected_declaration также создаёт объект (анонимного) защищённого типа.
Выполнение protected_definition создаёт защищённый тип и его первый подтип; оно также включает выполнение component_declaration и protected_operation_declaration в указанном порядке.
END_OF_DOCUMENT_MARKER
В рамках инициализации защищенного объекта, все ограничения на объект (см. 3.8) уточняются.
Уточнение protected_body не имеет других эффектов, кроме как установить, что защищенные операции данного типа могут отныне вызываться без срабатывания проверки Elaboration_Check.
Содержимое объекта заданного защищенного типа включает:
- Значения компонентов защищенного объекта, включая (в неявном виде) очередь ввода для каждой входящей точки, объявленной для защищенного объекта;
- Представление состояния ресурса выполнения, связанного с защищенным объектом (такой ресурс связан с каждым защищенным объектом).
Ресурс выполнения, связанный с защищенным объектом, должен быть получен для чтения или обновления любых компонентов защищенного объекта; он может быть получен (как часть защищенного действия — см. 9.5.1) либо для одновременного только для чтения доступа, либо для эксклюзивного доступа для чтения и записи.
В качестве первого шага завершения работы защищенного объекта, каждый вызов, оставшийся в очереди ввода объекта, удаляется из очереди, а Program_Error поднимается в месте соответствующего entry_call_statement.
Ограниченные (временные) ошибки
Вызов входящей точки или подпрограммы защищенного объекта после завершения работы этого объекта является ограниченной ошибкой. Если ошибка обнаружена, поднимается 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;