[Из песочницы] Оберон умер, да здравствует Оберон! Часть 1. Некоторые любят поактивней
Языкам программирования семейства Оберон не суждено было прорваться в мейнстрим, хотя они и оставили заметный след в 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, но его реализация может отсутствовать.
На этом я завершаю обзорную статью языка Активный Оберон, начать знакомство рекомендую с классического Оберона.
Ссылки: Багтрекер, исходный код ОС A2, включая компилятор Активного Оберона. Также в репозитории находятся варианты A2, запускаемые под Windows и *nix