Концепция статического создания дочерней задачи задачей-родителем осуществляется в языке Ада в два этапа: сначала строится объявление объекта типа "задача" внутри задачи-родителя (т. е. для объекта "задача" распределяются ресурсы), а затем активизируется объект "задача". Такая активизация происходит после завершения разработки декларативной части задачи-родителя (но до начала операторов задачи-родителя). В дальнейшем мы вкратце покажем синтаксические структуры, используемые для построения и активизации статически созданных задач.
[В среде системы i432 построение задачи соответствует созданию представляющего эту задачу объекта "процесс". Такой объект включает в себя oбъект "ресурс памяти" (Storage Resource Object - SRO) и определяет адресное пространство, используемое в качестве локального хранилища для данной задачи. Активизация задачи достигается путем помещения созданного объекта "процесс" в очередь в порту диспетчеризации (см. гл. 4), указывая этим на то, что соответствующий объект "процесс" (задача) готов направиться на фактический доступный процессор.]
Идентификатор задачи в языке Ада может быть объявлен статически непосредственным указанием того, что данный идентификатор является задачей. Аналогичным образом, идентификатор задачи может быть объявлен неявно. При этом сначала объявляется тип задачи, а затем ее идентификатор как экземпляр задачи данного типа. При любом объявлении программная структура задачи разбивается на часть спецификации и часть тела таким же образом, как это делается для процедур.
entry Print_winners( spread: in percent);может входить как объявление entry в часть спецификации для Portfolio_Server. Запрос на обслуживание, т. е. обращение к заданному входу задачи, должен соответствовать спецификации входа аналогично соответствию вызова процедуры спецификации этой процедуры.
Альтернативным способом является динамическое создание задачи. Например, задаче Task_Master не требуется создавать задачу для члена организации k до тех пор, пока он не сядет за терминал и сам не выдаст запрос на создание задачи. В конце данного раздела мы покажем, как это реализуется на языке Ада.
Приводимая на рис. 3.1 структура программы является весьма упрощенной, поскольку в ней не приводится способа, по которому каждая индивидуальная задача Member связывается с человеком, желающим получить доступ к портфелю. Отвлечемся на мгновение от разбора недостающих деталей и предположим следующее:
Задача Task_Master выполняется как "программа-ответчик" в процессе установления сеанса связи, отвечая на сигнал "внимание" от любого из нескольких терминалов. При начале некоторым лицом сеанса связи за каким-либо терминалом и подтверждении соответствующей идентификации задача Task_Master выдает сигнал о необходимости получения и выполнения в интерактивном режиме команд с терминала соответствующей (уже выполняющейся) задаче Member.
Согласно приведенной на рис. 2.5 структуре, каждая вводимая с терминала команда интерпретируется как запрос, обслуживаемый либо задачей Роrtfolio_Server, либо задачей Roster. В любом случае команда соответствующим образом форматируется и через обращение к соответствующему входу пересылается на вход задачи Portfolio_Server. Команда интерпретируется следующим образом:
После завершения выполнения запроса на обслуживание задачей-обслуживателем она освобождается и становится готовой принять следующий запрос. Запросы на обслуживание могут быть отложены, если задача-обслуживатель в данный момент занята выполнением некоторой операции с каким-либо устройством или иным действием, возможно связанным с завершением выполнения запроса. При выполнении различными задачами Master своих рабочих циклов и выдаче ими соответствующих запросов на обслуживание, а также при занятости задач Portfolio_Server и Roster_Server обслуживанием запросов возможно возникновение значительной степени параллелизма.
В данной структуре реализован механизм блокировки, поддерживаемый в языке Ада через средство, называемое "рандеву". В некоторых ситуациях блокировка может оказаться весьма полезной. При каждом вызове запросчиком обслуживателя запросчик блокируется от дальнейших действий до момента получения ответа от обслуживателя. Задержка, обусловленная ожиданием ответа, зависит от структуры задачи-обслуживателя и механизма управления запросами, которые ожидают обслуживания от данной задачи. (Более подробно эти вопросы рассматриваются в последнем разделе данной главы.)
Вследствие задержек, обусловливаемых механизмом рандеву, время отклика системы, приведенной на рис. 2.5, при определенных условиях может оказаться неудовлетворительным. Предположим, например, следующую ситуацию:
Мы полагаем, что Portfolio_Server отвечает на эти запросы в следующей последовательности:
Получив запрос от Member(1), Portfolio_Server обращается сначала к Roster_Server и ждет утвердительного ответа. Этот ответ задерживает прием запроса на чтение портфеля от Member(2), даже если Portfolio_Server в состоянии ответить на запрос Member(2) без помощи Roster_Server.
Предположим теперь, что Portfolio_Server отвечает на запрос от Member(2), который не требует работы задачи Roster_Server. Теперь Portfolio_Server не может принять запрос от задачи Member(3) до момента завершения текущего запроса "только чтение" от Member(2), даже если третий запрос не приводит к конфликтной ситуации при доступе к Club_Portfolio. Таким образом, в процессе обслуживания Member(2) Roster_Server вынужден бездействовать даже при наличии направленного к нему задачей Portfolio_Server необслуженного запроса.
Приведенный выше сценарий иллюстрирует ситуацию, в которой при использовании описанной ранее структуры задачи возможно возникновение задержек. При другой последовательности запросов простои будут меньшими. При небольших загрузках системы простой служебных задач не является критичным.
Проектировщик системы старается отыскать способ, позволяющий уменьшить вынужденное ожидание или простой процессов, особенно в тех случаях, когда задержки становятся весьма критичными с точки зрения производительности системы. Существует несколько способов решения этой проблемы.
Одним из способов является замена имеющегося в языке Ада механизма рандеву набором имеющихся в системе i432 альтернативных операторов коммуникации. Такие операторы имеются в поддерживаемых системой пакетах. Их применение сводится к выполнению инструкций SEND, RECEIVE и других имеющихся в системе i432 инструкций, полезных для обеспечения функционирования асинхронных межзадачных коммуникаций. Мы опишем эти операторы и расскажем об их применении в гл. 5.
[В некоторых программах возможно моделирование асинхронного обмена между задачами в рамках возможностей, имеющихся в стандартном языке Ада. Это может быть проделано различными способами. Например, запросчик может использовать порожденные "задачи-курьеры", каждая из которых направляет по одному запросу к задаче-обслуживателю. Такая тактика позволяет освободить задачу-запросчик, позволяя ей продолжать свою работу даже в случае блокировки задач-курьеров. В конце данного раздела рассматривается вопрос о том, как минимизировать время ожидания задачи-запросчика.]
Второй подход, обусловленный желанием придерживаться принятой в языке Ада модели задачи, предполагает альтернативу структуре, приведенной на рис. 3.1, обеспечивающую больше путей сообщения между задачами Member и двумя задачами-обслуживателями. Пример одной из таких структур приведен на рис. 3.2.
Несмотря на то что мы обсудим этот подход в конце данной главы, читателю предлагается ознакомиться вкратце с его наиболее существенными чертами.
Члены организации, обладающие особыми привилегиями, могут быть связаны с задачами согласно специальным категориям, отличающимся от категории Mernber_Task. Примером могут служить секретарь, который несет ответственность за поддержание списка членов организации, и казначей, контролирующий портфель акций. Теперь каждая категория задач-запросчиков передает свои запросы к обслуживателю через собственный пакет значимых операций над портфелем и списком членов организации. Эти пакеты (посредством приватных операций) осуществляют соответствующие обращения к Portfolio_Server или Roster_Server. Таким образом, секретарь организации может, например, обновлять список членов организации, в то время как другой член организации выдает запрос к портфелю.
Отметим, что возросший параллелизм достигается обеспечением независимых путей к задачам-обслуживателям, позволяя избежать блокировок, присущих предыдущему варианту. Однако это достигается ценой введения дополнительного уровня "косвенного обращения" в структуре программы аналогично тому, как это было сделано в пакете Member_0ps. Это приводит к появлению дополнительного шага на пути доступа к задачам-обслуживателям.