Www.adacore.com Ада-технологии - terra incognita для индустрии и образования Рыбин Сергей Игоревич НИВЦ МГУ, Москва, Россия AdaCore, Paris, France rybin@adacore.com.

Презентация:



Advertisements
Похожие презентации
Проектирование архитектуры ИСО 1. UML 2 Структура определения языка 4.
Advertisements

Глава 6. УПРАВЛЯЮЩИЕ СТРУКТУРЫ Оператор присваивания Простой и составной операторы Условный оператор Оператор множественного выбора Оператор цикла с предусловием.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 4 Трансформация логической модели в программный код Лекции читает кандидат технических.
Министерство образования Республики Беларусь Белорусский государственный университет Управляющие структуры языков программирования.
1 Программирование на языке Паскаль Ветвления. 2 Разветвляющиеся алгоритмы Задача. Ввести два целых числа и вывести на экран наибольшее из них. Идея решения:
ОДНОМЕРНЫЕ МАССИВЫ. РАБОТА С ЭЛЕМЕНТАМИ СТРУКТУРИРОВАННЫЕ ТИПЫ ДАННЫХ.
Таблица умножения на 8. Разработан: Бычкуновой О.В. г.Красноярск год.
Основы информатики Классы Заикин Олег Сергеевич zaikin.all24.org
OOП Инна Исаева. Подпрограмма – это большая программа, разделённая на меньшие части. В программе одна из подпрограмм является главной. Её задача состоит.
Лекция 7. Структура языка С/С++. Операторы ветвления: условный оператор if. Полное ветвление. Неполное ветвление. Оператор множественного выбора switch.
Урок-обобщение (7 класс – алгебра) МОУ "СОШ 45 г. Чебоксары" Кабуркина М. Н.1.
Основные виды ресурсов и возможности их разделения.
Массивы 9 класс. Основные теоретические сведения Примеры решения задач.
Основы программирования. 2 Циклы Цикл – это многократное выполнение одинаковой последовательности действий. цикл с известным числом шагов цикл с неизвестным.
Программирование на Pascal. Темы Повторение. Составные логические условия Повторение. Составные логические условия Повторение. Составные логические условия.
1 Знаток математики Тренажер Таблица умножения 2 класс Школа 21 века ®м®м.
Подпрограммы 1.Принцип модульности 2.Область действия переменных 3.Параметры подпрограмм 4.Модули.
ПРАКТИКУМ по предмету: Информатика Алгоритмический язык Турбо-Паскаль.

Лекция 4. Режимы работы микропроцессора. Взаимодействие микропроцессора с остальными устройствами Взаимодействие МП с остальными устройствами МПС происходит.
Транксрипт:

Ада-технологии - terra incognita для индустрии и образования Рыбин Сергей Игоревич НИВЦ МГУ, Москва, Россия AdaCore, Paris, France

Slide 2 (Очередная) попытка разорвать порочный круг: Ада (практически) отсутствует в современном российском ИТ-образовании Ада (практически) отсутствует в современной российской ИТ-индустрии Российские ИТ-специалисты не знакомы с Ада-технологиями и инструментарием Отсутствует «заказ» на подготовку специалистов, владеющих Ада-технологиями

Slide 3 Цели лекции Показать, что Ада-технологии существуют и являются существенной компонентой современной программной индустрии; Показать, что в Аде есть интересного и полезного, чего нет в других технологиях; Целью ни в коей мере не являются: –научиться программировать на Аде; –вдаваться в детали и подробности; –рассмотреть все интересные и полезные возможности языка

Slide 4 Общий план лекции Что такое Ада - рекламно-пропагандистский обзор (аудитории предлагается верить лектору на слово). Как язык может помогать писать надежный код и мешать ошибаться? Параллелизм, системы реального времени, асинхронные процессы – реализация привычной нам модели многопроцессного асинхронного мира высокоуровневыми конструкциями Ады. Где про это можно почитать, как и что можно взять, чтобы попробовать?

Slide 5 Что такое Ада? Язык программирования, определяемый стандартом ISO Ada Reference Manual, ISO/IEC 8652:2007(E) Ed. 3; Язык, первоначально разработанный в конце 70-х годов прошлого века по заказу министерства обороны США для использования в качестве единого языка военных встроенных систем; Язык, применяемый в настоящее время для разработки больших, долго живущих систем реального времени с повышенными требованиями к надежности; Язык, практически неизвестный современным российским инженерам и программистам ;

Slide 6 Современное состояние Ада-технологий - МИФЫ: Ада - мертвый язык, некогда популярный, но сейчас практически не используемый Ада - язык, предназначенный исключительно для военных встроенных систем И РЕАЛЬНОСТЬ: Ада всего лишь отсутствует на рынке «коробочных» продуктов, однако язык активно применяется, в частности, для разработки больших систем реального времени с повышенными требованиями к надежности Последняя версия стандарта Ады принята в 2007 году Число гражданских применений Ады сопоставимо с применениями в военной сфере Ада - не менее универсальный язык, чем С/С++ или Java.

Slide 7 Современное состояние Ада-технологий - МИФЫ: Ада - слишком большой и тяжелый язык для использования в небольшом проекте Ада-технологии неэффективны (трансляторы требуют огромных ресурсов, порождаемый код отличается большим объемом и низкой скоростью исполнения и т.п.) И РЕАЛЬНОСТЬ: Стандарт С++ превосходит стандарт Ады и по объему описания, и по сложности, тогда как Ада превосходит С++ по выразительным средствам Практически на каждой Ада- конференции присутствует робот Lego, управляемый Ада-программой Все современные индустриальные реализации современных индустриальных языков сопоставимы по эффективности (легко проверяется на практике)

Slide 8 Современное состояние Ада-технологий - МИФЫ: Ада-технологии слишком дороги В России нет специалистов, знающих Аду, а подготовка таких специалистов потребовала бы слишком больших затрат И РЕАЛЬНОСТЬ: Существуют полноценные БЕСПЛАТНЫЕ версии Ада-технологий (в частности, специально предназначенные для обучения) В России есть достаточное число Ада- энтузиастов, которые могут стать «точками кристаллизации» соответствующих коллективов разработчиков ( ru.org) Обучение Аде немногим сложнее обучения Паскалю и существенно проще обучения С++ Программист, знающий Паскаль (базовый язык российского ИТ-образования!), в состоянии освоить Аду в объеме, необходимом для начала практической работы, за неделю

Slide 9 Ада в мировой программной индустрии - пользователи системы программирования GNAT ABB Alcatel Space Air Traffic Control Netherlands Belgocontrol Boeing BAE Systems Ericsson Microwave System Eurocontrol Eurocopter Eurotunnel General Dynamics Harris Corporation Havelsan Hewlett-Packard Honeywell Indra Kongsberg Defense Lockheed Martin MBDA Ministry of Defense, the Netherlands NATO Paranor Philips Semiconductors ITEC PostFinance Raytheon Rockwell Collins Saab Selex Sistemi Integrati Siemens Transportation Systems SGI Thales...

Slide 10 Преимущества Ады для индустрии: Единственный язык, специально созданный для повышения надежности программного кода (при разработке и сопровождении больших долго живущих систем); Универсальность (язык может все, что могут другие индустриальные языки, и еще кое-что сверх этого); Стандартизация и отсутствие диалектов; Реальная кросс-платформенность; Поддержка кросс-технологий; Возможность непосредственного доступа к «железу»; Возможность многоязыкового программирования; Простота (при прочих равных условиях); Производительность (при прочих равных условиях);

Slide 11 Язык программирования и надежность. Ада была создана как средство преодоления кризиса в разработке ПО по заказам Пентагона, который готов был разразиться в 70-е годы прошлого века, причина кризиса – в катастрофическом падении надежности как вновь создаваемых систем, так и модификаций существующих систем в ходе их сопровождения; Язык был разработан на основе систематической процедуры на основе перечня требований, основным из которых было требование по обеспечению надежности кода как в ходе его создания, так и в процессе сопровождения;

Slide 12 Основные методы обеспечения надежности Ясный и надежный синтаксис: –программу один раз пишут и бесконечно много раз читают; –работа программиста в индустрии более чем на 90% состоит в изучении и модификации не им написанного кода; Комфорт и удобство разработчика: –готовые и удобные решения для часто встречающихся технологических потребностей; –удобные средства создания проблемно-ориентированных абстракций; –высокая производительность на полном жизненном цикле программной услуги; Болезнь легче предупредить, чем лечить: –если требования к результатам деятельности критичны, деятельность должна быть жестко регламентирована, регламент призван уменьшить число ошибок (все, что явным образом не разрешено – запрещено!); –язык должен мешать ошибаться при создании кода; –чем раньше обнаружится ошибка, тем проще и дешевле ее устранение;

Slide 13 Основные методы обеспечения надежности Классификация ошибок в программе на уровне стандарта языка. Стандарт явно определяет: –нарушение каких сформулированных в нем правил должны обнаруживаться при компиляции модуля; –нарушение каких правил должно обнаруживаться при сборке программы из отдельно компилируемых модулей; –нарушение каких требований должно приводить к возбуждению предопределенного исключения во время выполнения; –какие правила реализация не обязана проверять; Стандартизация языка при наличии средств контроля стандарта (если программа неправильна – то ни одна реализация ее не скомпилирует и не соберет в исполняемый модуль!)

Slide 14 Hello, World! Ада – прямой потомок Паскаля: with Ada.Text_IO; procedure Hello_World is begin Put_Line (Hello, World!); end Hello_World;

Slide 15 Синтаксис и надежность Опасность ошибиться и не заметить: Си - правильный код: if (the_signal == clear) { open_gates (...); start_train (...); } Но если перепутать = и==, получим формально корректный код: if (the_signal = clear) { open_gates (...); start_train (...); } В Аде такое невозможно: if The_Signal = Clear then Open_Gates (...); Start_Train (...); end if; В Аде присваивание := никогда не может оказаться частью конструкции, являющейся условием и быть перепутано со сравнением =. В Аде операторы четко отделены от выражений.

Slide 16 Синтаксис и надежность Опасность ошибиться и не заметить: Си - правильный код: if (the_signal == clear) { open_gates (...); start_train (...); } Если случайно поставить «лишнюю» точку с запятой, получим формально корректный код: if (the_signal == clear) ; { open_gates (...); start_train (...); } В Аде такое невозможно: if The_Signal = Clear then ; Open_Gates (...); Start_Train (...); end if; В Аде не бывает неявных пустых операторов, которые «вдруг» появляются перед ;. Данный код будет отвергнут как синтаксически некорректный

Slide 17 Синтаксис и надежность Полезные «мелочи» procedure P1 is... procedure P2 is... begin... end P2; begin... Bl1 : begin... Bl2 : begin... end Bl2;... end Bl1; end P1; record I : Integer; end record;... if Condition then for I in loop case Value is... end case; end loop; end if;

Slide 18 Прогнозирование и контроль. Прогнозирование и контроль свойств элементов программы - основное средство обеспечения надежности: –каждая используемая в программе сущность должна быть объявлена; –объявление полностью определяет свойства сущности; –каждая сущность может использоваться только в соответствии с ее свойствами, заданными в ее объявлении; –никакие неявные преобразования или изменения свойств сущности недопустимы; Все, что не разрешено (объявлением сущности), запрещено (при использовании сущности);

Slide 19 Строгая типизация в Аде -философия Что такое тип данных в языке программирования? –множество значений + набор применимых операций или все-таки –отражение содержательной роли объектов данных в проблемной области? Типы данных и надежность программ - философия Ады: –надежность программы возрастает, если программа максимально точно и подробно отражает модель проблемной области; –для каждого объекта данных важно определить его роль в (модели) проблемной области и проконтролировать, что каждый объект используется только в своей роли; Концепция строгой типизации: тип данных = содержательная роль объектов данных в модели проблемной области;

Slide 20 Строгая типизация в Аде - теория Все типы данных явно определены (объявлены) в программе, все они имеют имена и определения; Все объекты данных (и все их компоненты) имеют ровно один тип. Этот тип известен при объявлении объекта. Этот тип должен быть задан путем указания имени ранее объявленного типа данных; Все операции объявлены в тексте программы, все они имеют явно определенные типы параметров и результата (если он есть) Эти типы также должны быть заданы путем указания имен ранее объявленных типов данных. При вызове любой операции (присваивание тоже считается операцией!) проверяется, что типы операндов соответствуют заявленным типам параметров операции; Соответствие типов есть не соответствие структур значений, а совпадение имен (объявлений) типов; Все типы должны определяться статически (это никак не связано и никак не препятствует динамическому полиморфизму как части объектно- ориентированного программирования, далее мы рассмотрим динамический полиморфизм подробнее) Неявные преобразования типов недопустимы.

Slide 21 Строгая типизация в Аде – классический пример type Фрукты is new Integer; -- тип с теми же свойствами, что -- Integer, но ДРУГОЙ!!! type Яблоки is new Фрукты; type Апельсины is new Фрукты;... Я1, Я2 : Яблоки; А1, А2 : Апельсины; Ф : Фрукты;... Я1 := 5; -- можно Я1 := Я1 + Я2; -- можно А1 := Я1 + А2; -- нельзя - нет такого «+»! Ф := Я1; -- нельзя - разные типы источника и получателя «:=»! if Я1 + Я2 > Ф then -- и это недопустимо! Нет такого > … end if;

Slide 22 Строгая типизация в Аде – смена содержательной роли объекта Совсем строгая типизация на практике оказывается обременительной - иногда объекту данных надо в каком-то случае выступить в иной содержательной роли; Смена содержательной роли объекта данных не должна происходить сама собой, это должно быть осознанным действием программиста; Смена содержательной роли объекта должна быть локализована и легко заметна в тексте программы; Механизм явного преобразования типов

Slide 23 Производные типы и преобразование типа type Фрукты is new Integer; type Яблоки is new Фрукты; type Апельсины is new Фрукты; type Антоновка is new Яблоки; type Зеленая_Антоновка is new Антоновка; type Желтая_Антоновка is new Антоновка; Я : Яблоки; Я_Антоновка : Антоновка; Ж_Антоновка : Желтая_Антоновка; З_Антоновка : Зеленая_Антоновка; А : Апельсины; Ф : Фрукты;... Я_Антоновка := Антоновка (Ж_Антоновка) + Антоновка (З_Антоновка); Я := Яблоки (З_Антоновка) + Я; Ф := Фрукты (А) + Фрукты (Ж_Антоновка); А := Апельсины (Я); if Яблоки (Ж_Антоновка) + Яблоки (З_Антоновка ) > Яблоки (А) then... end if; Фрукты АпельсиныЯблоки Зеленая_ Антоновка Желтая_ Антоновка Антоновка

Slide 24 «Если нельзя, но очень хочется, то можно!» Иногда возникает необходимость преобразования типа между типами, вообще не имеющими друг к другу никакого отношения… Это можно сделать, но для этого придется специально настроить вот такой шаблон: generic type Source() is limited private; type Target() is limited private; function Ada.Unchecked_Conversion(S : Source) return Target; и применить результат настройки к нужным объектам (то есть, сделать такое случайно, «не заметив», невозможно).

Slide 25 Полезные «мелочи»… Все намерения программиста должны быть явно обозначены type Week_Day is (Mon, Tue, Wen, Thu, Fri, Sat, Sun); Day : Week_Day;... case Day is when Mon.. Thu => Working_Like_Dog; when Sat => Drinking; when Sun => Fishing; end case; -- Но что происходит в пятницу??? -- Такой код не будет скомпилирован! Статическая борьба с «дохлыми» ссылками: package P is type T is...; type T_Ptr is access all T; Global : T_Ptr; end P;... procedure Q is X : aliased T; Local : T_Ptr := X'Access; -- Так нельзя! -- Local может быть присвоен чему угодно, -- в т.ч. и Global begin Global := X'Access; -- Нельзя! Global := Local; -- Нельзя! Global := XUnchecked_Access; -- Можно, но под личную -- ответственность автора... end Q;

Slide 26 Подтипы и исключительные ситуации Тип данных – это: –концептуально - содержательная роль объектов данных в программе; –технически – множество значений + совокупность операций; Подтип – это ограничение множества значений в рамках той же содержательной роли; Реализация сама проверяет, что присваиваемое значение попадает в подтип, определенный для данного объекта данных (принадлежит подтипу); В случае нарушения подтипового ограничения при выполнении программы возбуждается предопределенное ограничение Constraint_Error;

Slide 27 Подтипы - пример procedure Автопилот is type Скорость is digits 8 range ; function Данные_Спидометра return Скорость is... end Данные_Спидометра; subtype Безопасная_Скорость is Скорость range ; Текущая_Скорость : Безопасная_Скорость;... begin... loop Текущая_Скорость := Данные_Спидометра;... end loop;... exception when Constraint_Error => Включить_Аварийный_Сигнал; Нажать_На_Тормоз;... end Автопилот;

Slide 28 Подтипы и исключительные ситуации Для одного типа данных можно определить сколько угодно разных подтипов; Подтиповые ограничения формулируются статически, но определяются и проверяются – динамически subtype Безопасная_Скорость is Скорость range Min (Режим_Полета).. Max (Режим_Полета); Подтипы можно применять при конструировании сложных структур данных; Существуют различные виды ограничений; Подтиповые ограничения всегда проверяются динамически;

Slide 29 Проблемы при сборке программы package P1 is function F1 return Integer; end P1; with P1; package body P2 is X2 : Integer := P1.F1; function F2 return Integer is begin return X2; end F2; end P2; with P2; package body P1 is X1 : Integer := P2.F2; function F1 return Integer is begin return X1; end F1; end P1; package P2 is function F2 return Integer; end P2; Реализация Ады обязана определить, что не существует корректного порядка включения кода, порождаемого модулями P1 и P2, в исполняемый код, а потому никогда не будет создан исполняемый код для программы, в состав которой входят эти модули.

Slide 30 На обеспечение надежности работают и такие языковые механизмы, как: Разделение спецификации (интерфейса) и реализации (тела) для каждого программного модуля и невозможность доступа к телам со стороны клиентов модуля; Приватные типы; Правила видимости имен; Правила раздельной компиляции; Контрактная модель настройки шаблонов; …

Slide 31 Чего стоят такие меры обеспечения надежности? Статический контроль (как при раздельной компиляции модулей, так и при сборке программ) приводит только лишь к утяжелению транслятора, никак не сказываясь на размерах и быстродействии исполняемого кода; Динамический контроль (подтиповые ограничения) незначительно утяжеляют исполняемый код, при необходимости они могут быть (выборочно) отключены;

Slide 32 И что они дают? IEEE Software, 1987, #1, pp40-44: производительность разработчиков на полном цикле (>= 20_000 SLOC): –Ада - 12 строк/день –другие языки - 10 строк/день распределение затрат в проекте:

Slide 33 Асинхронные процессы в Аде Наш мир состоит из взаимодействующих асинхронных процессов, следовательно, программы, встроенные в реальный мир и управляющие реальными процессами, должны уметь работать с асинхронными процессами; Взаимодействие асинхронных процессов – сложное явление; Программы с асинхронными процессами существенно сложнее последовательных программ; Чем может помочь язык программирования? –Предоставление высокоуровневых средств описания асинхронных процессов и управления ими; –Данные средства должны быть согласованы с привычными нам моделями взаимодействия асинхронных процессов; –Данные средства должны быть ориентированы на устойчивые к ошибкам парадигмы и технологии работы с асинхронными процессами;

Slide 34 Определение асинхронного процесса. Асинхронному процессу соответствует специальный программный модуль – задача ( task ); Запуск, завершение и взаимодействие процессов управляется языковыми конструкциями и правилами, не требуется никаких обращений к каким-либо библиотекам (никаких spawn, fork и тому подобного);

Slide 35 Два асинхронных процесса на 20 строк кода 1 with Ada.Text_IO; 2 procedure Tasking_Example is 3 Finished : Boolean := False; 4 pragma Atomic(Finished); 5 6 task Outputter; -- task specification 7 8 task body Outputter is -- task body 9 Count : Integer := 1; 10 begin 11 while not Finished loop 12 Ada.Text_IO.Put_Line(Integer'Image(Count)); 13 Count := Count + 1; 14 delay 1.0; -- one second 15 end loop; 16 Ada.Text_IO.Put_Line("Terminating"); 17 end Outputter; begin 20 delay 20.0; -- twenty seconds 21 Finished := True; 22 end Tasking_Example; процесс Tasking_Example процесс Outputter результат работы этой программы: Terminating

Slide 36 Задачи - интерфейс Каждый программный модуль в Аде состоит из спецификации, описывающей интерфейс модуля с внешним миром, и тела, описывающего внутреннее устройство/семантику/поведение модуля; Интерфейс (спецификация) модуля-задачи может содержать только объявления входов ; Для внешнего мира вход задачи выглядит как процедура – он может иметь параметры, его можно вызвать ; В теле задачи каждому входу этой задачи должен соответствовать оператор приема входа ( accept ), который выполняется при вызове входа задачи (в момент рандеву );

Slide 37 Рандеву как средство синхронизации и обмена данными task T1 is entry E1 (X : in Some_Type); end T1; task body T1 is Var1 : Some_Type;... begin... accept E1 (X : in Some_Type) do Var1 := X; end E2;... T2.E2;... end T1; task T2 is entry E2; end T2; task body T2 is Var2 : Some_Type;... begin... T1.E1 (Var2);... accept E2;... end T1; рандеву ждет вызова ждет приема

Slide 38 Асимметричное рандеву как модель поведения «клиент- мастер» Рандеву - вызывающая задача в точке вызова входа и вызываемая в точке приема вызова должны оказаться одновременно; Вызывающая задача знает, вход какой именно задачи она вызывает (имя входа доступно только в префиксной форме, префикс - имя задачи, которой принадлежит вход), вызываемая - не знает, кто именно ее вызвал, лишь бы параметры были соответствующих типов - поэтому рандеву асимметричное ; Модель поведения « клиент-мастер »: у клиента есть часы, он хочет их починить и выбирает именно часовую мастерскую, часовому мастеру все равно, кто именно к нему пришел, лишь бы принес чинить часы, а не холодильник. К одному и тому же мастеру могут выстраиваться очереди клиентов - ожидающие рандеву очереди вызовов входов, выполнение оператора приема для данного входа отпускает из очереди первый вызов; Пока задача ждет, чтобы ее вызов входа обслужили (или чтобы ее вход вызвали), она просто стоит на месте;

Slide 39 Взаимодействие асинхронных процессов Описать отдельно взятый процесс относительно просто, основная сложность – во взаимодействии процессов: –совместное использование несколькими процессами одного и того же ресурса (разделяемые ресурсы); –взаимное исключение (в каждый момент времени ресурсом может пользоваться не более одного процесса); –«тупики»; Внешняя и внутренняя дисциплины использования разделяемых ресурсов: –кто и где следит за тем, чтобы разделяемый ресурс использовался корректно – сам ресурс или нечто (некто?) вне его?

Slide 40 Взаимодействие асинхронных процессов: Адский подход Процесс должен уметь выбирать варианты своего поведения в зависимости от своего состояния и готовности других процессов к взаимодействию с ним; Средства управления взаимодействием процессов ориентированы на внутреннюю дисциплину использования разделяемых ресурсов как на более надежную: –разумно устроенный разделяемый ресурс допускает только корректное использование! Каждый процесс проектируется в предположении, что мир, с которым он взаимодействует, устроен разумно, и все, что от него требуется – гарантировать разумность своего собственного поведения (процесс сам может для кого-то оказаться разделяемым ресурсом!);

Slide 41 Постановка задачи «взаимодействие через буфер» Из внешней среды поступают однородные объекты (сообщения), с каждым из которых необходимо проделать два разных действия – анализ и синтез. Анализ и синтез выполняются независимо для разных объектов, для одного и того же объекта анализ следует за синтезом. При этом существенными являются временные характеристики: –минимальное время между поступлением сообщений – τ –максимальное время анализа – τ – ε, где ε

Slide 42 Решение - интерфейс Точка зрения пользователя (внешней среды) - надо иметь возможность по мере необходимости передавать сообщение, а по мере готовности - получать ответ Эти действия независимы и могут происходить асинхронно package Анализ_Синтез is type Сообщение is array (1.. 80) of Character; type Ответ is new Сообщение; task Анализ is entry Принять (X : in Сообщение); end Анализ; task Синтез is entry Выдать (X : out Ответ); end Синтез; end Анализ_Синтез;

Slide 43 Решение - как им пользоваться? package Генератор_Сообщений is task Генератор is entry Start; end Генератор; end Генератор_Сообщений; package Потребитель_Сообщений is task Потребитель is entry Start; end Потребитель; end Потребитель_Сообщений ; with Генератор_Сообщений; with Потребитель_Сообщений ;... procedure Main is Ch : Character; begin Генератор_Сообщений.Генератор.Start; Потребитель_Сообщений.Потребитель.Start;... end Main; -- Мы не рассматриваем проблему -- завершения задач! with Анализ_Синтез; use Анализ_Синтез; package body Генератор_Сообщений is task body Генератор is Message : Сообщение; begin accept Start; loop Message := Сформировать_Сообщение (...); Анализ.Принять (Message); end loop; end Генератор; end Генератор_Сообщений; with Анализ_Синтез; use Анализ_Синтез; package body Потребитель_Сообщений is task body Потребитель is Answer : Ответ; begin accept Start; loop Синтез.Выдать (Answer); Использовать_Ответ (Answer); end loop; end Потребитель; end Потребитель_Сообщений;

Slide 44 Реализация взаимодействием через буфер Генератор_ Сообщений Потребитель_ Сообщений Анализ. Принять Синтез. Выдать ответ сообщение интерфейс реализация Буфер разбор

Slide 45 Реализация - общая структура -- Воспользуемся классической -- абстракцией буфера -- ограниченного размера generic Размер : in Positive := 10; type Элемент is private; package Любой_Буфер is procedure В_Буфер (X : in Элемент); procedure Из_Буфера (X : out Элемент); function Пуст return Boolean; function Полон return Boolean; end Любой_Буфер; with Любой_Буфер; package body Анализ_Синтез is type Разбор is new Сообщение; task Буфер is entry Положить (X : in Разбор); entry Достать (X : out Разбор); end Буфер; task body Анализ is...; task body Синтез is...; task body Буфер is...; end Анализ_Синтез; Осталось написать тела...

Slide 46 Реализация - тела задач Анализ и Синтез task body Анализ is Моё_Сообщение : Сообщение; Готов : Разбор; begin loop accept Принять (X : in Сообщение) do Моё_Сообщение := X; end Принять; анализ сообщения, -- формирование значения -- переменной Готов Буфер.Положить (Готов); end loop; end Анализ; task body Синтез is Моё_Сообщение : Разбор; Готов : Ответ; begin loop Буфер.Достать (Моё_Сообщение); Синтез ответа, -- формирование значения -- переменной Готов accept Выдать (X : out Ответ) do X := Готов; end Готов; end loop; end Синтез;... в предположении, что Буфер - «умный» и позволяет себя использовать только корректно...

Slide 47 Реализация «умного» Буфера -- подготовка структуры -- данных package Локальный_Буфер is new Любой_Буфер (Размер => 30; Элемент => Разбор); use Локальный_Буфер; task body Буфер is begin loop select when not Полон => accept Положить (X : in Разбор) do В_Буфер (X); end Положить; or when Полон or else (not Пуст and then ПоложитьCount)= 0 => accept Достать (X : out Разбор) do Из_Буфера (X); end Достать; or terminate; end select; end loop; end Буфер; охранные ограничения операторы приема альтернатива завершения

Slide 48 Семантика оператора отбора Вычисляются все охранные ограничения (порядок вычисления недетерминирован) и выбираются «открытые» альтернативы приема (охранное ограничение отсутствует или истинно); Среди «открытых» альтернатив приема выбираются готовые к немедленному рандеву (очереди вызовов соответствующих входов не пусты); Среди «открытых» и готовых к рандеву альтернатив приема недетерминированным образом выбирается одна и выполняется; Если нет «открытых» и готовых к рандеву альтернатив приема, выполнение оператора зависит от его завершающей части –если таковой является альтернатива завершения, задача завершается, если она «больше никому не нужна»;

Slide 49 Та же самая задача – на основе внешней дисциплины использования разделяемых ресурсов Попробуйте решить тут же задачу, если единственным средством организации взаимодействия процессов является семафор… –при помощи семафора несложно обеспечить, чтобы процессы Анализ и Синтез использовали буфер в режиме взаимного исключения, но как обеспечить отсутствие тупиков (процесс Анализ захватил полностью заполненный буфер в исключительное использование)? –как обеспечить приоритет процесса Анализ при использовании буфера?

Slide 50 Разновидности оператора отбора - альтернатива задержки Альтернатива задержки: если есть «открытые» альтернативы, но нет готовых к рандеву - ждем указанное время. Если за это время не появился подходящий вызов - выполняем операторы альтернативы задержки; Если нам за 0.1 секунды не сообщили новое значение температуры - бьем тревогу! loop select accept Считать_Значение (T : in Temperature) do Текущая_Температура := T; end Считать_Значение; -- анализируем новое -- значение температуры... or delay 0.1; raise Сломался_Градусник; end select; end loop;

Slide 51 Разновидности оператора отбора - else часть. ELSE-часть: если рандеву немедленно невозможно по любой причине - выполняем операторы после else ; «Драйвер градусника» - постоянно пересчитываем текущую температуру и готовы выдать ее по первому требованию loop select accept Выдать_Значение (T : out Temperature) do T := Текущая_Температура; end Выдать_Значение; else -- считаем значение для -- Текущая_Температура... end select; end loop;

Slide 52 Выбор варианта поведения задачей - клиентом Оператор отбора есть оператор отбора вызова входа для обработки этого вызова, он используется в задаче- мастере. Похожая конструкция может использоваться задачей- клиентом при вызове входа; В отличие от оператора отбора вызова входа, который может иметь несколько альтернатив приема, многоальтернативных конструкций для вызова входа нет;

Slide 53 Условный вызов входа Если рандеву немедленно невозможно - так и не надо, займемся своими делами! loop select Card.Read (C); -- Вызов входа Read -- задачи Card Обработать_Карту (C); exit; else Локальные_Вычисления; end select; end loop;

Slide 54 ВременнОй (Timed) вызов входа Если рандеву немедленно невозможно - ждем не более явно оговоренного (в операторе задержки) времени. Если не дождались своей очереди - отказываемся от вызова входа select Архив.Записать (X); or delay 5.0; Put_Line (К сожалению, архивная & система занята); end select;

Slide 55 Асинхронная передача управления (по истечению интервала времени) Асинхронная передача управления – это возможность прервать последовательность действий при наступлении некого события. Таким событием может быть вызов входа или наступление (истечение) некоторого момента (интервала) времени; -- предположим, мы не можем себе позволить -- тратить на некоторые действия слишком -- много времени select delay 5.0; Put_Line (Calculation is too long!); then abort Horribly_Complicated_Recursive_Function (X, Y); end select; -- по истечении 5 секунд вычисление -- Horribly_Complicated_Recursive_Function -- будет прервано

Slide 56 Асинхронная передача управления (по наступлению события (вызову входа) Командный интерпретатор с возможностью нажатия Ctrl-C; Вызов входа Wait_For_Interrupt задачи Terminal (нажатие Ctrl-C) приводит к прерыванию обработки текущей команды loop select Terminal.Wait_For_Interrupt; -- Совмещенный с Ctrl-C -- вызов входа Put_Line (Interrupted); then abort Put_Line ( ); Get_Line (Command, Last); Process_Command (Command (1.. Last)); end select; end loop ;

Slide 57 Защищенные записи - зачем? Наш буфер в решении задачи «Анализ-Синтез» хорош всем, кроме одного - он реализован задачей, то есть - активным процессом со всеми накладными расходами и для программиста (надо заботиться, в частности, о запуске и завершении), и для реализации; На самом деле буфер - разделяемый объект данных, для которого всего лишь требуются операции, обеспечивающие корректную и удобную работу с ним при условии использования несколькими асинхронными процессами; Эту возможность обеспечивают защищенные записи ( protected records ): средства определения объектов данных – и одновременно дисциплины их использования;

Slide 58 Защищенные записи - что это такое? Защищенная запись объединяет данные, операции доступа к ним и особые правила выполнения этих операций; Как и обычная запись, защищенная запись имеет поля, но они скрыты от непосредственного доступа; Доступ к полям возможен лишь при помощи защищенных операций, объявленных в видимой части; Защищенные операции это: –функции; –процедуры; –входы; protected T is объявления защищенных -- операций private объявления полей объявления скрытых -- защищенных операций end T; protected body T is тела защищенных операций end T;

Slide 59 Простейший пример - разделяемая переменная Требования к разделяемой переменной: –ее значение могут одновременно читать несколько процессов; –изменять значение переменной может лишь один процесс; –во время изменения значения должно быть невозможно считать это значение; protected Variable is function Read return Item; procedure Write (New_Value: Item); private Data: Item; end Variable; protected body Variable is function Read return Item is begin return Data; end Read; procedure Write (New_Value: Item) is begin Data := New_Value; end Write; end Variable; -- Использование разделяемой переменной X := Variable.Read;... Variable.Write(New_Value => Y);

Slide 60 Защищенные операции Защищенные операции «принадлежат» защищенному объекту, при их вызове защищенный объект выступает в качестве неявного параметра вызова; Защищенные функции могут лишь читать значения полей, защищенные процедуры и входы могут и читать и менять значения полей; одновременно может выполняться несколько вызовов функций одного и того же защищенного объекта; одновременно может выполняться не более одного вызова защищенной процедуры или входа (при этом не могут выполняться вызовы защищенных функций того же объекта); с защищенным входом связаны очереди вызовов и барьерные ограничения

Slide 61 Выполнение защищенных операций Защищенный объект (protected object - PO) может находится в одном из двух состояний: –«открыт» - готов к обработке вызова защищенной процедуры или входа, может обрабатывать вызовы защищенных функций; –«закрыт» - занят обработкой вызова защищенной процедуры или входа, при этом вызовы защищенных операций не могут «проникнуть» в PO и «неорганизованно» (нет очередей!) «толпятся» снаружи; Вызов защищенной процедуры или входа «захватывает» РО. Выполнение защищенной процедуры начинается немедленно. Для защищенного входа проверяется барьерное ограничение. Если оно истинно - вызов входа выполняется. Иначе вызов ставится в очередь к входу;

Slide 62 Выполнение защищенных операций Самое интересное происходит после завершение выполнения защищенной процедуры или входа, и после того, как в очередь добавлен новый вызов (PO все еще «закрыт»!): –перевычисляются барьерные ограничения для всех входов (ведь только что выполнившаяся процедура или вход могли изменить ситуацию, а длина очереди – часть состояния объекта!) –если обнаруживаются входы с истинными значениями барьеров и непустыми очередями входов) - недетерминированным образом выбирается один вход из очереди и выполняется; –и все снова - перевычисление барьеров, проверка очередей, пока не окажется, что нет ни одного входа с истинным барьером и непустой очередью. Лишь тогда PO, наконец, «открывается»; Барьерные ограничения не могут зависеть от (фактических) параметров входов!

Slide 63 «Умный» буфер protected type Bounded_Buffer is entry Put (X: in Item); entry Get (X: out Item); private A : Item_Array (1.. Max); I, J : Integer range 1.. Max := 1; Count : Integer range 0.. Max := 0; end Bounded_Buffer; protected body Bounded_Buffer is entry Put (X : in Item) when Count 0 is begin X := A(J); J := J mod Max + 1; Count := Count - 1; end Get; end Bounded_Buffer; -- Использование буфера: -- * возможно только в режиме -- взаимного исключения; -- * тупики исключены; My_Buffer : Bounded_Buffer;... My_Buffer.Put (Something);... My_Buffer.Get (To_Something);

Slide 64 «Многозначный» семафор Семафоры - это обычно «системные» (т.е. внеязыковые) объекты. Однако семафор легко реализуется как PO; В данном PO присутствуют все три типа защищенных операций; PO могут иметь дискриминанты; protected body Counting_Semaphore is entry Secure when Current_Count > 0 is begin Current_Count := Current_Count - 1; end Secure; procedure Release is begin Current_Count := Current_Count + 1; end Release; function Count return Integer is begin return Current_Count; end Count; end Counting_Semaphore; protected type Counting_Semaphore (Start_Count: Integer := 1) is entry Secure; procedure Release; function Count return Integer; private Current_Count: Integer := Start_Count; end Counting_Semaphore;

Slide 65 Сигналы Как и семафоры, обычно реализуются «системными» переменными, но в Аде легко реализуются как PO; Реализация классического сигнала; Почему Wait - вход, а Signal - процедура? protected body Сигнал is entry Ждать when Есть_Сигнал is begin Есть_Сигнал := False; -- сигнал получен end Ждать; procedure Послать is begin Есть_Сигнал := True; -- устанавливаем барьер -- для Ждать в True end Послать; end Сигнал; protected Сигнал is entry Ждать; -- ждать появления сигнала procedure Послать; -- послать сигнал private Есть_Сигнал: Boolean := False; end Event;

Slide 66 Сигнал «Слушайте все!» Другая разновидность сигнала - его получают сразу все ожидающие, но если сигнала никто не ждет - сигнал пропадает; Пример перенаправления вызова входа в другую очередь; protected body Сигнал is entry Ждать when Есть_Сигнал is begin null; -- тело «пустое»! end Ждать; entry Послать when True is -- барьер всегда истинный! begin if Ждать'Count > 0 then Есть_Сигнал := True; requeue Обновить; end if; end Послать; entry Обновить when Ждать'count = 0 is begin Есть_Сигнал := False; end Обновить; end Сигнал; protected Сигнал is entry Ждать; entry Послать; private entry Обновить; -- приватный вход! Есть_Сигнал : Boolean := False; end Сигнал;

Slide 67 То же самое - но намного проще! PO может не содержать данных, а его операции могут иметь пустой код, но даже такой PO может оказаться полезным! Реализуемая этим PO функциональность полностью эквивалентна предыдущему примеру (с булевским флагом и requrue) ; protected Сигнал is entry Ждать; entry Послать; end Сигнал; protected body Сигнал is entry Ждать when Послать'Count > 0 is begin null; end Ждать; entry Послать when Ждать'Count = 0 is begin null; end Послать; end Сигнал;

Slide 68 Что еще можно рассказать об асинхронных процессах в Аде? Задачные и защищенные типы: задачи и защищенные записи как объекты данных и элементы структур данных; Динамическое создание задач и защищенных объектов; Управление приоритетами; Исключения, возникающие в ходе рандеву; Подходы к разработке многопроцессных программ; Ограничения, повышающие предсказуемость поведения систем с асинхронными процессами; …

Slide 69 Система программирования GNAT ( Включает в себя: –компилятор Ады, соответствующий последней редакции стандарта (Ada Reference Manual, ISO/IEC 8652:2007(E) Ed. 3 ), являющийся частью многоязыковой среды gcc; –компиляторы С, С++; –среду разработки GPS; –традиционный набор средств разработки (отладчик, средства навигации, возможности форматирования на лету, …); –развитый инструментарий (метрики, статический анализ размера стека, средства обнаружения утечек памяти, статический контролер кода, …); –AWS, XMLAda, GTKAda,... Существует в виде: –индустриальной версии; –версии для университетов; –свободно доступной версии для разработки GPL-программ; Все исходные тексты доступны, основной язык реализации – Ада. Интерфейс всех компонент системы программирования GNAT одинаков на всех платформах, где она реализована.

Slide 70 Система программирования GNAT – индустриальная версия Распространяется путем продажи контрактов на техническую поддержку (24x7x365). Техподдержка включает: –развитие технологии по запросам пользователей; –консультации по языку и по системе программирования GNAT; –содержательная реакция о сообщении об обнаруженной проблеме в течение одного рабочего дня; –предоставление версий технологии с устраненными дефектами; Реализована на всех индустриальных платформах; Кросс-компиляторы для LynxOS, VxWorks, VxSIM, поддержка Bare Boards, high integrity версии.

Slide 71 GNAT Academic Program (GAP) Распространяется бесплатно среди учебных заведений, для получения достаточно прислать по факсу заполненную анкету (1 страница); Доступна в среде MS Windows, Linux, Sparc-Solaris, по функциональности полностью идентична индустриальной версии; Обмен опытом и учебными материалами с другими участниками GAP-программы; Поддержка пользователей (без предоставления версий с исправленными ошибками);

Slide 72 GNAT GPL Можно бесплатно взять на Полностью под GPL, позволяет разрабатывать только GPL- программы; Поддержка разработчиков отсутствует;

Slide 73 Где и что почитать про Аду? –русскоязычный сайт, созданный нашими Ада-энтузиастами –среди прочего, содержит: –книгу по Аде-95 –достаточно полный перечень ссылок на англоязычные Ада-ресурсы Обзор и обоснование проектных решений для версии стандарта 1995 года (Ada 95 Rationale) -

Slide 74 Заключение Ада является существенным компонентом мировой программной индустрии Не использовать Аду просто потому, что о ней не известно специалистам по информационным технологиям, едва ли разумно Отечественные специалисты по ИТ должны иметь достаточно информации о современном состоянии Ада технологий, чтобы принимать осознанные решения относительно их использования или неиспользования в тех или иных проектах