Основы объектно-ориентированного проектирования

         

Концепции сопрограмм


Наряду с базисными ОО-механизмами язык Simula предлагает интересное понятие - сопрограмма.

Понятие сопрограммы рассматривалось при обсуждении параллелизма. Дадим краткое напоминание. Сопрограммы моделируют параллельные процессы, существующие в операционных системах или системах реального времени. У процесса больше концептуальной свободы, чем у подпрограммы. Например, драйвер принтера полностью ответственен за то, что происходит с принтером, им управляемым. Он не только ответственен за абстрактный объект, но и имеет собственный алгоритм жизненного цикла, часто концептуально бесконечный. Форма процесса принтера может быть приблизительно такой:

from some_initialization loop forever "Получить файл для печати"; "Напечатать его" end

В последовательном программировании связь между единицами программы асимметрична: когда один программный блок вызывает другой, то последний выполняется, после чего возвращает управление вызывающему блоку в точке вызова. Процессы равноправны: каждый процесс выполняется сам по себе, прерываясь временами для предоставления информации другому процессу или ожидая ее получения.

Сопрограммы спроектированы подобным же образом, но для выполнения в одном потоке управления. (Последовательная эмуляция параллельного выполнения называется квази-параллелизмом.) Сопрограмма прерывает свое собственное выполнение и предлагает продолжить выполнение (resume) другой сопрограмме в ее последней точке прерывания; прерванная сопрограмма позже может продолжиться сама.


Рис. 17.1.  Последовательное выполнение сопрограмм

Сопрограммы особенно полезны, когда каждая из нескольких связанных деятельностей имеет собственную логику. Каждая из них может быть задана последовательным процессом, и отношение "хозяин-слуга", характерное для обычных подпрограмм, является неадекватным. Типичным примером является преобразование входных данных в выходные, где на структуру входных и выходных файлов накладываются различные ограничения. Такой случай будет обсуждаться ниже.


Simula представляет сопрограммы как экземпляры классов. Это уместно, поскольку сопрограммы почти всегда нуждаются в длительно хранимых данных, и с ними ассоциируется абстрактный объект. Как отмечалось выше, класс в Simula может иметь тело. В классе, представляющем абстракцию пассивных данных, оно будет служить только для инициализации экземпляров классов (эквивалент нашей процедуры создания). В сопрограмме оно будет описанием процесса. Тело сопрограммы - это обычно цикл вида

while continuation_condition do begin ... Действия ...; resume other_coroutine; ...Действия ... endДля некоторых сопрограмм условием continuation_condition часто является True, что эквивалентно бесконечному процессу (несмотря на то, что хотя бы одна сопрограмма должна завершиться).

Система, основанная на сопрограммах, обычно имеет основную программу, сначала создающую ряд объектов - сопрограмм, а затем продолжает одну из них:

corout1 :- new C1; corout2 :- new C2; ... resume coroutiКаждое выражение new создает объект и приступает к выполнению его тела. Но квазипараллельная природа сопрограмм (в отличие от истинного параллелизма процессов) поднимает проблему инициализации. Для процессов каждое new порождает новый процесс, запускает его, возвращая тут же управление исходному процессу. Но здесь только одна сопрограмма может быть активной. Если выражение new запустило основной алгоритм сопрограммы, то исходный процесс не получит вновь управление - у него не будет возможности создать C2 после порождения C1.

Simula решает эту проблему посредством инструкции detach. Сопрограмма может выполнить detach, возвращая управление блоку, создавшему его посредством new. Тела сопрограмм почти всегда начинаются с detach (если необходимо, после инструкции инициализации), а дальше обычно следует цикл. После выполнения своего detach сопрограмма приостановится до тех пор, пока главная, или другая, сопрограмма не продолжит ее выполнение.


Содержание раздела