Справочник по Ada 2012
9.5.1 Защищенные подпрограммы и защищенные действия
Защищенная подпрограмма — это подпрограмма, объявленная непосредственно внутри protected_definition. Защищенные процедуры обеспечивают эксклюзивный доступ для чтения и записи к данным защищенного объекта; защищенные функции обеспечивают одновременный доступ для чтения только к данным.
Статическая семантика
Внутри тела защищенной функции (или функции, объявленной непосредственно внутри protected_body), текущий экземпляр окружающего защищенного блока определяется как константа (то есть, его подкомпоненты можно читать, но не обновлять). Внутри тела защищенной процедуры (или процедуры, объявленной непосредственно внутри protected_body), и внутри entry_body текущий экземпляр определяется как переменная (обновление разрешено).
Для типа, объявленного с помощью protected_type_declaration или для анонимного типа объекта, объявленного с помощью single_protected_declaration, можно указать следующее язык-определенное представление типа:
Exclusive_Functions
Тип аспекта Exclusive_Functions — Boolean. Если не указан (включая наследование), аспект имеет значение False.
Значение True для этого аспекта указывает, что защищенные функции ведут себя так же, как защищенные процедуры по отношению к взаимному исключению и обработке очереди (см. ниже).
Защищенная процедура или вход — это эксклюзивная защищенная операция. Защищенная функция типа защищенного типа P является эксклюзивной защищенной операцией, если аспект Exclusive_Functions для P имеет значение True.
Динамическая семантика
Для выполнения вызова защищенной подпрограммы, вычисление имени или префикса и ассоциаций параметров, и любое присваивание параметров in out или out происходит так же, как при вызове обычной подпрограммы (см. 6.4). Если вызов — внутренний (см. 9.5), тело подпрограммы выполняется так же, как при вызове обычной подпрограммы. Если вызов — внешний, то тело подпрограммы выполняется как часть нового защищенного действия над целевым защищенным объектом; защищенное действие завершается после выполнения тела подпрограммы. Защищенное действие также может быть запущено вызовом входа (см. 9.5.3).
Новое защищенное действие не запускается для защищенного объекта, пока другое защищенное действие над тем же защищенным объектом не завершится, если только оба действия не являются результатом вызова неэксклюзивной защищенной функции. Это правило выражается в терминах ресурса выполнения, связанного с защищенным объектом:
- Запуск защищенного действия над защищенным объектом соответствует получению ресурса выполнения, связанного с защищенным объектом, либо для эксклюзивного доступа для чтения и записи, если защищенное действие предназначено для вызова эксклюзивной защищенной операции, либо для одновременного доступа только для чтения в противном случае;
- Завершение защищенного действия соответствует освобождению связанного ресурса выполнения.
После выполнения эксклюзивной защищенной операции над защищенным объектом, но до завершения связанного защищенного действия, обслуживаются очереди входов (если таковые имеются) защищенного объекта (см. 9.5.3).
Ограниченные (времени выполнения) ошибки
Во время защищенного действия является ограниченной ошибкой вызов операции, которая потенциально блокирует. Следующие операции определяются как потенциально блокирующие:
- выражение select_statement;
- выражение accept_statement;
- выражение entry_call_statement;
- выражение delay_statement;
- выражение abort_statement;
- создание или активация задачи;
- внешний вызов защищенной подпрограммы (или внешнее переупорядочение) с тем же целевым объектом, что и защищенное действие;
- вызов подпрограммы, тело которой содержит потенциально блокирующую операцию.
Если обнаружена ограниченная ошибка, возникает исключение Program_Error. Если ошибка не обнаружена, ограниченная ошибка может привести к тупиковой ситуации или (вложенному) защищенному действию над тем же целевым объектом.
Некоторые определяемые языком подпрограммы потенциально блокируют. В частности, подпрограммы определяемых языком пакетов ввода-вывода, которые манипулируют файлами (явно или неявно), потенциально блокирующие. Другие потенциально блокирующие подпрограммы идентифицируются при их определении. Когда не указано как потенциально блокирующие, определяемая языком подпрограмма является неблокирующей.
ПРИМЕЧАНИЯ
19 Если две задачи пытаются запустить защищенное действие над защищенным объектом, и не более одной из них вызывает защищенную функцию, то только одна из задач может продолжить. Хотя другая задача не может продолжить, она не считается заблокированной и может потреблять ресурсы обработки, пока ожидает своей очереди. Нет языка-определённого порядка или очереди, предполагаемых для задач, конкурирующих за запуск защищенного действия — на многопроцессорных системах такие задачи могут использовать ожидание с проверкой; для однопроцессорных систем см. D.3, «Блокирование с потолочным приоритетом».
20 Тело защищенного блока может содержать объявления и тела локальных подпрограмм. Они не видны за пределами защищенного блока.
21 Тело защищенной функции может содержать внутренние вызовы других защищенных функций, но не защищенных процедур, потому что текущий экземпляр является константой. С другой стороны, тело защищенной процедуры может содержать внутренние вызовы как защищенных функций, так и процедур.
22 Внутри защищенного действия внутренний вызов защищенной подпрограммы или внешний вызов защищенной подпрограммы с другим целевым объектом не считается потенциально блокирующей операцией.
23 Предикат pragma Detect_Blocking может использоваться для обеспечения того, что все выполнения потенциально блокирующих операций во время защищенного действия вызывают Program_Error. См. H.5.
Примеры
Примеры вызовов защищенных подпрограмм (см. 9.4):
Shared_Array.Set_Component(N, E);
E := Shared_Array.Component(M);
Control.Release;
E := Shared_Array.Component(M);
Control.Release;