Как уже говорилось, внутри программы на языке Ада задачи могут создаваться динамически ("по запросу"). В предыдущем примере все двадцать зaдaч Member_Tasks, задачи Portfolio_Server и Roster_Server активизируются после "проработки" всех объявлений в задаче Task_Master. Каждая из них может быть создана в тот момент, когда это необходимо, и прервана после выполнения своих функций, а затем при необходимости создана вновь. Задача Task_Master, являющаяся программой-ответчиком, создает задачу в момент вхождения пользователя в систему и удаляет ее по окончании сеанса связи.
В языке Ада экземпляр задачи создается динамически путем объявления сначала ссылочного типа (access) для данного типа задачи, затем объявлением переменной ссылочного типа и, наконец, присвоением переменной указателя на новый экземпляр типа задачи. Новый экземпляр типа задачи формируется в результате вычисления выражения генератора. Например, обратившись к рис. 3.1, мы можем заменить объявление
Member: аrrаy(1..20) of Member_Task;
на
type Member_Ptr is access Member_Task; type Member_Pool is аrrаy(1..20) of Member_Ptr; Member: Member_Pool;
объявив этим Member как массив, в котором каждому элементу может быть присвоено значение указателя для экземпляра типа Member_Task (описатель доступа к объекту "процесс" в терминах i432). Оператор вида
Member(k) := new Member_Task;
заданный в контексте приведенных выше объявлений, в процессе своего выполнения динамически создает новые экземпляры Member_Task, используя генератор
new Member_Task
и присваивая Member(k) полученное значение указателя.
Предположим теперь, что в нашей системе с портфелем акций задачи Member создаются динамически по выше описанной схеме. Таким образом, мы можем рассматривать каждую задачу Member как задачу-запросчик. (В ее части спецификации не требуется указания входов, поскольку статически созданная задача Member_Task должна иметь по крайней мере один вход для сигнализации Метber_Task о начале пользователем сеанса работы с системой.)
В схеме, приведенной на рис. 3.1, задачи Member выдают запросы к Portfolio_Server и косвенно к Roster_Server. Создание этих задач динамически существенных преимуществ не дает. Кроме того, поскольку коммуникации между задачей Task_Master и порожденными ею задачами не требуется, задача Task_Master не оказывает никаких услуг (не имеет входов в части спецификации).
Перед тем как приступить к обсуждению тел задач, мы сделаем последнее замечание относительно рис. 3.2 и задач, создаваемых динамически. В примере на рис. 3.2 мы решили отделить членов организации, обладающих особыми привилегиями (например, секретаря), от рядовых сотрудников, создав для этого отдельные задачи для администрации клуба. (Текст программ для этих специальных задач может не отличаться от задач для обычных сотрудников, но их списки with будут, разумеется, различными!) Динамическое создание этих отдельных задач для секретаря и казначея по-прежнему не представляет трудности. На рис. 3.3 предлагается пример текста программы, который мог бы быть помещен в Task_Master.
-- к списку with добавляются Secy_Ops и Treas_0ps. task type Secy; -- Только запросчик. task body Secy is separate; -- Заглушка. task type Treas; -- Только запросчик. task body Treas is separate; -- Заглушка. Secretary is access Secy; -- Объявление переменной типа "указатель". Treasurer is access Treas; -- Еще одно объявление переменной типа "указатель". -- -- Операторы внутри begin . . . end части Task_Master: -- Secretary:= new Secy; -- Создается новая задача Secy, a Secretary -- приcваивается указатель на нее. Treasurer:= new Treas; -- Создается новая задача Treas, a Treasurer -- присваивается указатель на нее. Рис. 3.3. Этапы динамического создания задач Secretary и Treasurer для структуры на рис. 3.2.