Языкам программирования семейства Оберон не суждено было прорваться в мейнстрим, хотя они и оставили заметный след в IT-индустрии. Однако и операционные системы, написанные на этих языках (являясь одновременно и программными каркасами различных решений и средами разработки), и сами языки программирования используются в учебной, исследовательской и промышленной сферах и по сей день, понуждая к творчеству и экспериментам, развиваясь и впитывая новые веянья индустрии и влияя на неё.
Этой обзорной статьёй я открываю серию статей, посвящённых языку Активный Оберон и операционной системе A2, написанной на этом языке.
Итак, встречайте — Активный Оберон
Первая публикация по Активному Оберону появилась в 1997 году, но понятно, что язык и его реализация появились несколько раньше. За эти годы произошло много изменений в языке, переработана среда времени выполнения, написана операционная система A2.
Особенностью языка, отличающей его от других языков программирования, является концепция Активных Объектов — объектов, инкапсулирующих поток выполнения. Активный Оберон расширяет язык Оберон, вводя объектный тип Объект, понятие Активность, связанная с объектом (поток), а также механизмы синхронизации и защиты от одновременного доступа. Реализация таких механизмов на уровне языка позволяет упростить разработку и реализацию многопоточных приложений и снижает количество ошибок, связанных с проблемой защиты и синхронизации.
В секции импорта подключаемые модули могут иметь псевдонимы, различные модули могут иметь один и тот же псевдоним, формируя из нескольких модулей некое подобие пространства имён. В таких модулях имена экспортированных сущностей не должны пересекаться.
Например:
IMPORT Example := Example1, Example := Example2;
В Активном Обероне реализованы улучшенные массивы (математические и тензорные), структурные массивы (объекты, совместимые с улучшенными массивами), комплексные типы, операции для объектов, улучшенных массивов и комплексных типов, делегаты, совместимые как с процедурами модуля так и с методами объекта. Вместо множественного наследования используется концепция множественного наследования интерфейсов.
Синтаксис языка в процессе развития практически не изменяется — вместо этого вводятся семантические модификаторы, изменяя семантику синтаксических конструкций, присутствующих в языке. Список модификаторов заключаются в фигурные скобки {}.
Так, для описания делегата используется модификатор процедуры DELEGATE:
Example1 : PROCEDURE{DELEGATE, REALTIME} ( VAR parameter : LONGINT ) : BOOLEAN;
В примере описана процедурная переменная Example1, указывающую на делегат — процедуру или метод реального времени, принимающие переменную типа длинное целое по ссылке и возвращающие значение логического типа.
Методы описываются внутри объекта. Все методы в Активном Обероне являются виртуальными. Методы, перед именем которых стоит знак & являются конструкторами и вызываются автоматически при создании объекта. Компилятор выбирает требуемый конструктор по сигнатуре вызова встроенной процедуры NEW, предназначенной для создания сущностей ссылочного типа. Объекты и методы могут также иметь модификаторы ABSTRACT и FINAL с понятной семантикой. Операции (операторы) могут описываться как на уровне объекта, так и на уровне модуля, за исключением некоторых операторов, описываемых только на уровне объекта (по крайней мере в текущей реализации).
Активные Объекты и модель многопоточности
Объект может иметь тело — завершающий блок операторов, выполняемый после инициализации объекта. Если тело объекта помечено модификатором ACTIVE (возможно с указанием приоритета), то такой объект называется активным. Как уже говорилось, активность (поток) инкапсулирована в объекте и создаётся в момент инстанцирования активного объекта. Активность существует пока выполняется тело активного объекта. Активный объект продолжает существовать, пока существует его активность, даже если на него нет ссылок, после чего он становится пассивным и может быть утилизирован в обычном порядке.
Коммуникация между активностями производится через вызовы методов активных и не активных объектов.
Защита от одновременного доступа к состояниям объекта осуществляется поддержкой на уровне языка монопольных областей (exclusive regions) — последовательности операторов, заключённых в операторные скобки BEGIN… END, помеченные модификатором EXCLUSIVE, — соответствующих концепции критических областей Бринча Хансена. Если монопольная область охватывает всё тело объекты, он называется монопольным и совмещает концепцию критических областей Хансена с концепцией процедуры монитора Хоара. В отличии от процедур монитора Хоара, методы объекта не обязаны быть монопольными, и могут наблюдать не синхронизированные состояния объекта. Модуль считается объектом с одним экземпляром. Компилятор и среда времени выполнения гарантируют, что в монопольной области может находиться не более одной активности одновременно.
Таким образом, модель защиты в Активном Обероне — монитор, размещенный в экземпляре объекта (instance-based monitor).
Главная идея монитора в том, что с ним связан инвармант — выражение, определяющее внутреннее, непротиворечивое состояние и доказывающее правильность его поведения. Инициализаторы объекта устанавливают инвариант, а монопольные методы его поддерживают.
Для синхронизации в Активном Обероне используется оператор AWAIT, тогда, как большинство реализаций мониторов используют условные переменные Хоара на основе очередей Хансена. Оператор AWAIT принимает в качестве аргумента логическое условие продолжения выполнения, в случае несоблюдение которого активность приостанавливается, а захваченная монопольная область освобождается до момента, когда условие выражения станет истинным. Активность продолжит работу когда снова сможет войти в отпущенную ранее монопольную секцию. Условия продолжения пересчитываются только когда какая-либо активность выходит из монопольной секции.
Пример описания активного объекта и использования монопольной секции:
TYPE Timer* = OBJECT VAR timer: Objects.Timer; handler: Objects.EventHandler; timeout, running: BOOLEAN; PROCEDURE &Init*; BEGIN NEW(timer); timeout := FALSE; running := TRUE; END Init; PROCEDURE SetTimeout*(h: Objects.EventHandler; ms: LONGINT); BEGIN handler := h; Objects.SetTimeout(timer, HandleTimeout, ms) END SetTimeout; PROCEDURE CancelTimeout*; BEGIN Objects.CancelTimeout(timer); END CancelTimeout; PROCEDURE HandleTimeout; BEGIN {EXCLUSIVE} timeout := TRUE END HandleTimeout; PROCEDURE Finalize*; BEGIN {EXCLUSIVE} Objects.CancelTimeout(timer); running := FALSE END Finalize; BEGIN {ACTIVE} WHILE running DO LOOP BEGIN {EXCLUSIVE} AWAIT(timeout OR ~running); IF ~running THEN EXIT END; timeout := FALSE END; handler() END END END Timer;
Управление памятью.
В Активном Обероне применяется автоматическое управление памятью, с использованием сборщика мусора реального времени. Это значит, что активности реального времени могут приостанавливать процесс сборки мусора. В участках кода реального времени запрещены операции выделения памяти за этим следит компилятор. Процедуры, методы и активности реального времени помечаются модификатором REALTIME. Не все реализации компилятора и среды выполнения поддерживают процессы реального времени.
Переменные, помеченные модификатором UNTRACED относятся к нетрасируемым указателям и не отслеживаются механизмами автоматического управления памятью.
В языке синтаксически поддерживается оператор DISPOSE, но его реализация может отсутствовать.
На этом я завершаю обзорную статью языка Активный Оберон, начать знакомство рекомендую с классического Оберона.
Ссылки:
ссылка на оригинал статьи http://habrahabr.ru/post/258917/
Добавить комментарий