Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

9.5 Межзадачная коммуникация

Основным средством межзадачной коммуникации являются вызовы к записям и защищённым подпрограммам. Вызовы защищённых подпрограмм позволяют координировать доступ к общим данным. Вызовы записей позволяют заблокировать вызывающую задачу до выполнения заданного условия (а именно, что соответствующая запись открыта — см. 9.5.3), и затем обмениваться данными или управляющей информацией напрямую с другой задачей или косвенно через общий защищённый объект.

Статическая семантика

Когда имя или префикс обозначает запись, защищённую подпрограмму или префиксный вид примитивной подпрограммы ограниченного интерфейса, первым параметром которой является управляющий параметр, то имя или префикс определяет объект-мишень следующим образом:
  • Если это прямое_имя или расширенное имя, которое обозначает объявление (или тело) операции, то объект-мишень неявно задаётся текущей экземпляром задачи или защищённого блока, непосредственно окружающего операцию; вызов с таким именем определяется как внутренний вызов;
  • Если это выбранный_компонент, который не является расширенным именем, то объект-мишень явно задаётся объектом, обозначаемым префиксом имени; вызов с таким именем определяется как внешний вызов;
  • Если имя или префикс представляет собой разыменование (неявное или явное) значения доступа к защищённой подпрограмме, то объект-мишень определяется префиксом атрибута доступа атрибута_ссылка, который изначально породил значение доступа; вызов с таким именем определяется как внешний вызов;
  • Если имя или префикс обозначает объявление_переименования_подпрограммы, то объект-мишень определяется по имени переименованного объекта.
Вызов записи или защищённой подпрограммы использует имя или префикс, который неявно определяет объект-мишень, как указано выше, или является вызовом (непрефиксного вида) примитивной подпрограммы ограниченного интерфейса, первым параметром которой является управляющий параметр, в этом случае объект-мишень идентифицируется явно первым параметром. Этот последний случай является внешним вызовом.
Соответствующее определение объекта-мишени применяется к заявлению_переотправки (см. 9.5.4), с соответствующим различием между внутренней переотправкой и внешней переотправкой.

Правила легальности

Если имя или префикс определяет объект-мишень, и имя обозначает защищённую запись или процедуру, то объект-мишень должен быть переменной, если префикс не относится к атрибуту_ссылке атрибута Count (см. 9.9).
Внутренний вызов защищённой функции не должен происходить внутри выражения предопределения (см. 6.1.1) защищённой операции или внутри выражения_по_умолчанию спецификации_параметра защищённой операции.

Динамическая семантика

В теле защищённой операции текущий экземпляр (см. 8.6) непосредственно окружающего защищённого блока определяется объектом-мишенью, указанным (неявно или явно) в вызове (или переотправке) защищённой операции.
Любой вызов защищённой процедуры или записи целевого защищённого объекта определяется как обновление объекта, как и переотправка на такую запись.

Синтаксис

synchronization_kind ::= By_Entry | By_Protected_Procedure | Optional

Статическая семантика

Для объявления примитивной процедуры синхронизированного помеченного типа может быть указан следующий определяемый языком аспект представления с помощью спецификации_аспекта (см. 13.1.1):
Синхронизация

Если указан, то определение аспекта должно быть synchronization_kind.
Наследуемые подпрограммы наследуют аспект Synchronization, если таковой имеется, от соответствующей подпрограммы родительского или предкового типа. Если переопределяющая операция не имеет напрямую указанного аспекта Synchronization, то аспект Synchronization наследуемой операции наследуется переопределяющей операцией.

Правила легальности

synchronization_kind By_Protected_Procedure не должен применяться к примитивной процедуре интерфейса задачи.
Процедура, для которой указан synchronization_kind By_Entry, должна быть реализована в виде записи. Процедура, для которой указан synchronization_kind By_Protected_Procedure, должна быть реализована в виде защищённой процедуры. Процедура, для которой указан synchronization_kind Optional, может быть реализована в виде записи или процедуры (включая защищённую процедуру).
Если примитивная процедура переопределяет унаследованную операцию, для которой аспект Synchronization был указан как By_Entry или By_Protected_Procedure, то любое указание аспекта Synchronization, применённого к переопределяющей операции, должно иметь тот же synchronization_kind.
В дополнение к местам, где обычно применяются правила легальности (см. 12.3), эти правила также применяются в закрытой части экземпляра обобщённого блока.

Статическая семантика

Для блока программы, записи задачи, формального пакета, формальной подпрограммы, формального объекта анонимного типа доступа к подпрограмме, литерала перечисления и для подтипа (включая формальный подтип) определён следующий определяемый языком операционный аспект:
Неблокирующий
Этот аспект определяет ограничение блокировки для объекта; он должен быть задан статическим булевым выражением. определение_аспекта может быть опущено из спецификации этого аспекта; в этом случае аспект для объекта — True.
Аспект Nonblocking может быть указан для всех объектов, для которых он определён, за исключением защищённых операций и записей задач. В частности, Nonblocking может быть указан для формальных параметров обобщений.
Когда аспект Nonblocking имеет значение False для объекта, объект может содержать потенциально блокирующую операцию; такой объект разрешает блокировку. Если аспект имеет значение True для объекта, объект считается неблокирующим.
Для экземпляра обобщения и объектов, объявленных в таком экземпляре, аспект определяется аспектом Nonblocking для соответствующего объекта обобщённого блока, и с аспектами Nonblocking фактических параметров обобщения, используемых объектом. Если аспект непосредственно задан для экземпляра, заданное выражение должно иметь то же значение, что и аспект Nonblocking экземпляра (после и с аспектами используемых фактических параметров). При отсутствии аспекта Use_Formal все фактические параметры обобщения предполагаются используемыми объектом (см. H.7.1).
Для (защищённой или задач) записи аспект Nonblocking — False.
Для литерала перечисления аспект Nonblocking — True.
Для предопределённого оператора элементарного типа аспект Nonblocking — True. Для предопределённого оператора составного типа аспект оператора такой же, как и аспект Nonblocking для типа.
Для разыменования типа доступа к подпрограмме аспект Nonblocking — такой же, как и аспект целевой подпрограммы.
Для базового подтипа скалярного (под)типа аспект Nonblocking — True.
Для наследуемой примитивной диспетчерской подпрограммы, которая является нулевой или абстрактной, подпрограмма неблокирующая тогда и только тогда, когда соответствующая подпрограмма по крайней мере одного предка неблокирующая. Для любой другой унаследованной подпрограммы она неблокирующая тогда и только тогда, когда соответствующая подпрограмма родителя неблокирующая.
За исключением случаев прямого указания, переопределения диспетчерских операций наследуют этот аспект.
END_OF_DOCUMENT_MARKER
Если не указано иное, для формального подтипа, формального пакета или формальной подпрограммы аспект Nonblocking совпадает с аспектом фактического подтипа, пакета или подпрограммы.
Если не указано иное, для непервого подтипа S, аспект Nonblocking совпадает с аспектом подтипа, определённого в указании подтипа, определяющего S; если не указано иное для первого подтипа производного типа, аспект Nonblocking совпадает с аспектом подтипа предка.
Если не указано иное, для любой другой программной единицы, первого подтипа или формального объекта, аспект Nonblocking сущности определяется аспектом Nonblocking для самой внутренней программной единицы, содержащей сущность.
Если для библиотечной единицы не указано иное, аспект Nonblocking равен True, если библиотечная единица объявлена чистой, и False в противном случае.
Следующие операции определены как потенциально блокирующие:
  • операция select_statement;
  • операция accept_statement;
  • операция entry_call_statement или вызов процедуры, которая переименовывает или реализуется посредством входа;
  • операция delay_statement;
  • операция abort_statement;
  • создание или активация задачи;
  • во время защищённого действия, внешний вызов защищённой подпрограммы (или внешнее переупорядочение) с тем же объектом-целью, что и защищённое действие.
Если определённая языком подпрограмма допускает блокирование, то вызов подпрограммы является потенциально блокирующей операцией.

Правила законности

Часть текста программы называется неблокирующей областью, если она находится в параллельной конструкции или если самая внутренняя окружающая программная единица неблокирующая. Неблокирующая область не должна содержать следующее:
  • операцию select_statement;
  • операцию accept_statement;
  • операцию delay_statement;
  • операцию abort_statement;
  • создание или активацию задачи.
Кроме того, параллельная конструкция не должна содержать вызов вызываемой сущности, для которой аспект Nonblocking равен False, а также не должна содержать вызов вызываемой сущности, объявленной внутри обобщённой единицы, использующей обобщённый формальный параметр с аспектом Nonblocking False (см. аспект Use_Formal в H.7.1).
Наконец, неблокирующая область, которая находится вне параллельной конструкции, не должна содержать вызов вызываемой сущности, для которой аспект Nonblocking равен False, за исключением случаев, когда область находится внутри обобщённой единицы, а вызываемая сущность связана с обобщённым формальным параметром обобщённой единицы, или вызов находится в aspect_definition определения аспекта утверждения для сущности, которая допускает блокирование.
Для целей вышеуказанных правил, entry_body считается неблокирующим, если немедленно окружающая защищённая единица неблокирующая.
Для подтипа, для которого аспект Nonblocking равен True, любое предикатное выражение, применимое к подтипу, должно содержать только конструкции, разрешённые непосредственно внутри неблокирующей программной единицы.
Подпрограмма должна быть неблокирующей, если она переопределяет неблокирующую операцию диспетчеризации. Вход не должен реализовывать неблокирующую процедуру. Если унаследованная подпрограмма диспетчеризации допускает блокирование, то соответствующая подпрограмма каждого предка должна допускать блокирование.
Не допускается прямое указание аспекта Nonblocking для первого подтипа полного представления типа, имеющего частичное представление. Если аспект Nonblocking полного представления унаследован, он должен иметь то же значение, что и частичное представление, или иметь значение True.
Аспект Nonblocking должен быть прямо указан для первого подтипа производного типа только в том случае, если он имеет то же значение, что и аспект Nonblocking подтипа предка, или если он указан как True. Аспект Nonblocking должен быть прямо указан для непервого подтипа S только в том случае, если он имеет то же значение, что и аспект Nonblocking подтипа, определённого в subtype_indication, определяющего S, или если он указан как True.
Для типа доступа к объекту, который неблокирующий, операции Allocate, Deallocate и Storage_Size на его пуле памяти должны быть неблокирующими.
Для составного типа, который неблокирующий:
  • Все подтипы компонентов должны быть неблокирующими;
  • Для типа записи или расширения, каждый вызов в default_expression компонента (включая дискриминанты) должен вызывать операцию, которая неблокирующая;
  • Для управляемого типа подпрограммы Initialize, Finalize и Adjust (если таковые имеются) должны быть неблокирующими.
Предопределённый оператор равенства для составного типа, за исключением случая, когда он для типа записи или расширения записи, и оператор переопределён примитивным оператором равенства, является незаконным, если он неблокирующий и:
  • для типа записи или расширения записи родительский примитивный оператор "=" допускает блокирование; или
  • некоторый компонент принадлежит типу T, и:
T является типом записи или расширением записи, имеющим примитивный оператор "=" , который допускает блокирование; или
T не является ни типом записи, ни расширением записи, и T имеет предопределённый оператор "=" , который допускает блокирование.
При обобщённом инстанцировании:
  • фактическая подпрограмма, соответствующая формальной неблокирующей подпрограмме, должна быть неблокирующей (в этом случае фактическая подпрограмма, являющаяся входом, не допускается);
  • фактический подтип, соответствующий формальному неблокирующему подтипу, должен быть неблокирующим;
  • фактический объект, соответствующий формальному объекту типа неблокирующего доступа к подпрограмме, должен быть типа неблокирующего доступа к подпрограмме;
  • фактический экземпляр, соответствующий формальному неблокирующему пакету, должен быть неблокирующим.
В дополнение к местам, где обычно применяются правила законности (см. 12.3), вышеупомянутые правила также применяются в приватной части экземпляра обобщённой единицы.
ПРИМЕЧАНИЕ Аспект synchronization_kind By_Protected_Procedure подразумевает, что операция не будет блокироваться.


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API