Студопедия

Главная страница Случайная лекция


Мы поможем в написании ваших работ!

Порталы:

БиологияВойнаГеографияИнформатикаИскусствоИсторияКультураЛингвистикаМатематикаМедицинаОхрана трудаПолитикаПравоПсихологияРелигияТехникаФизикаФилософияЭкономика



Мы поможем в написании ваших работ!




Обзор примера

Читайте также:
  1. Аналитические обзоры
  2. Введение в экологию. Обзор современных экологических проблем.
  3. Внутренняя двойственность лингвистики, на примерах
  4. Возможности и ограничения систематических обзоров
  5. Вопрос 2. Обзор основных законов и закономерностей обучения.
  6. Данные рассматриваемого примера
  7. Доказательная медицина. Систематические обзоры. Метаанализ
  8. Индикаторы кругового обзора (ИКО).
  9. Исторический обзор возникновения и эволюция создания тугоплавких неметаллических и силикатных материалов. Современные направления науки в разработке и создании твердых материалов
  10. Конвенция о правах ребенка (краткий обзор статей, касающихся прав детей)

Далее рассмотрим пример - упрощенный фрагмент телекоммуникационной системы из области мобильной телефонии. Данная система реализует стык пользовательского интерфейса мобильного телефона (клавиатурный ввод и дисплейная индикация) и верхнего уровня интерфейса телефона с наземной сетью.

Эта система, без сомнения, является реактивной. Она асинхронно взаимодействует с пользователем телефона и сетью. Она прерываема - например, обязана обслуживать экстренные вызовы (связь с МЧС), находясь практически в любых состояниях. Работа системы ограничена строго заданными временными интервалами (это, к сожалению, в примере будет затронуто лишь слегка, иначе он получился бы слишком сложным). Система работает по различным сценариям, имея, кроме главного, "хорошего" сценария, множество "боковых веток". Наконец, архитектура системы организована в виде параллельно работающих компонент.

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

Успешными средствами моделирования реактивных систем являются диаграммы композитных структур (вариант для компонент) в связке с диаграммами конечных автоматов. Конечный автомат создается для композитной компоненты. Он использует сообщения и операции, определенные в интерфейсах компонент, для взаимодействия с окружением. В паре два этих типа диаграмм позволяют создавать содержательные и наглядные спецификации, по которым генерируется целевой код СРВ. Все это и хочется продемонстрировать.

На рис.10.6 представлена диаграмма последовательностей, на которой обозначены главные действующие лица примера и основной сценарий их взаимодействия. Сразу после включения телефонной трубки (пользователь нажал нужную кнопку на аппарате) клавиатура (Keybroad), с помощью сообщения Switch-on, создает компоненту UserDriver, которая, в свою очередь, создает компоненту Main. После этого компонента UserDriver, с помощью сообщения DPINInput, посылает дисплею команду отобразить приглашение на ввод PIN. Введенный пользователем PIN пересылается с клавиатуры компоненте UserDriver, а та переправляет его компоненте Main, где происходит его проверка. Если PIN правильный, то компонента Main начинает искать сеть, посылая оповещение об этом компоненте UserDriver (сообщение SearchForPLMN). Последняя, в свою очередь, командует дисплею отобразить картинку поиска сети (сообщение DSearchPLMN ). Когда сеть найдена, Main посылает UserDriver сообщение HomePLMN, и та, после его получения, предлагает дисплею отобразить картинку-сообщение, что полный сервис телефона доступен пользователю (сообщение DHomePLMN). Компонента Main переходит в состояние Idle и готова обслуживать запросы пользователя телефона и входящие запросы из сети.

Рис. 10.6. Главный сценарий примера

 

Из четырех сущностей, представленных на диаграмме с рис.10.6, нас интересуют только две - UserDriver и Main. Оставшиеся не являются программным обеспечением, поэтому здесь не рассматриваются. Компоненты UserDriver и Main представлены на рис.10.7.




Рис. 10.7. Компоненты Main и UserDriver

 

В нашем примере поведение компоненты Main определяется с помощью диаграммы конечных автоматов. Иллюстративный вариант этой спецификации представлен на рис.10.8. Данная диаграмма создана для того, чтобы функциональность компоненты Main стала понятной в первом приближении: имена состояний и события обозначены по-русски, нет описания действий в переходах и т. д. Формальная спецификация поведения компоненты Main будет представлена ниже (нетерпеливые могут посмотреть уже сейчас на рис.10.17). UML позволяет создавать такие промежуточные, эскизные спецификации и хранить их наравне с основными.

Рис. 10.8. Иллюстративное описание поведения компоненты Main

 

Прокомментируем рис.10.8. При включении трубки компонента Main переходит в состояние "Ожидание PIN". Если PIN введен верно, то далее компонента Main оказывается в состоянии "Поиск сети" и ищет свою сеть - ту, в которой абонент зарегистрирован и информация о которой хранится в его трубке. Если своя сеть найдена, то происходит переход в состояние "Ожидание запроса". В этом состоянии компонента Main способна обрабатывать запросы на установку соединения - как исходящего, от абонента трубки, так и входящего, поступившего из сети. Но эта функциональность уже отсутствует в нашем примере, дабы не усложнять его чрезмерно.

Это был самый "хороший" сценарий, в результате исполнения которого телефонная трубка включилась и готова обслуживать абонента. Теперь рассмотрим самый "плохой" сценарий, когда телефон есть, сеть есть, а позвонить никуда, кроме как в милицию, нельзя (гм, что может быть хуже…). В состоянии "Ожидание PIN" компонента Main может принять три попытки ввода неверного PIN. Если вторая или третья попытка окажется удачной, то дальнейшие события разворачиваются так, как описано выше. Если же и в третьей попытке был введен неверный PIN, то происходит переход в состояние "Ожидание PUK ". В этом состоянии принимается десять попыток ввести верный PUK и после десятой попытки происходит переход в состояние "Блокирована". Если компонента Main находится в этом состоянии, то трубка может позволить абоненту сделать только экстренный выз ов (милиция, скорая помощь), а также выключить трубку. Теперь рассмотрим различные "боковые ветки", спецификации которых посвящен остаток диаграммы.

В состоянии "Ожидание PUK" пользователь может ввести правильный PUK, и после этого он снова получит возможность вводить PIN.

  1. В состоянии "Поиск сети", кроме того, что было рассказано, может произойти следующее.
  2. Своя сеть не найдена, но найдена чужая сеть. Сервис, который доступен абоненту в этом случае, будет зависеть от того, есть ли у него роуминг. Но компонента Main каждые 0,5 секунд будет проверять, не появилась ли своя сеть.
  3. Не найдена никакая сеть. В этом случае компонента Main будет продолжать поиск сети.

В состояниях "Ожидание PIN", "Ожидание PUK", "Блокирована", "Чужая сеть" компонента Main обеспечивает абоненту обработку экстренного вызова и возвращается обратно в то состояние, в котором ее прервали. Наконец, в любом состоянии компонента Main способна обработать сообщение о выключении трубки, посланное пользователем с клавиатуры через компоненту UserDriver, и завершить свою работу.

Детали структурной модели

Компоненты UserDriver и Main реализуют интерфейсы UD и Main соответственно, которые подсоединяются к ним через порты. Чтобы корректно функционировать, каждая из этих компонент нуждается в интерфейсе, определяемом другой компонентой. Все это можно видеть на рис.10.7.

Спецификации интерфейсов UD и Main представлены на рис.10.9. В этих интерфейсах есть только сообщения. Напомним, что компонента реализует такой интерфейс, когда умеет обрабатывать сообщения, обозначенные в ее интерфейсе.


Рис. 10.9. Описание интерфейсов UD и Main

 

И, наконец, определим необходимые внутренние операции и атрибуты компоненты Main (рис.10.10). Данные свойства компоненты, разумеется, являются private, т. е. не видны "наружу".

Рис. 10.10. Внутренние свойства компоненты Main

 

Выше было представлено целых три диаграммы (рис.10.7, рис.10.9,рис.10.10), где описываются одни и те же сущности - компоненты Main и UserDriver, а также их интерфейсы. Конечно, это же самое можно было сделать, используя одну-единственную диаграмму, но получилось бы громоздко и существенно менее понятно.

Состояние

Базовой конструкцией конечного автомата является состояние (state) - стабильный "отрезок жизни" компоненты, когда она готова к обработке событий и делает это в зависимости от предыдущей истории поведения.

"Стабильность" состояния понимается в одном из следующих смыслов:

  • ожидание компонентой внешних событий - обращений к ней других компонент, поступление сигналов к системе извне и пр.;
  • выполнение компонентой некоторой фоновой деятельности, которая может быть прервана при получении компонентой какого-либо события, требующего обработки (эта деятельность может определяться, например, с помощью деятельности в состоянии - см. ниже);
  • выполнение компонентой определенного связного "куска" штатной работы - например, прохождение определенного этапа алгоритма.

Важно не только то, что компонента очередной раз перешла в стабильное положение, даже если сама стабильность по качеству одна и та же - например, простое ожидание. Существенно также то, что было до этого момента, т. е. история поведения компоненты. Пусть, например, компонента Main ожидает события срабатывания таймера в состояниях PLMNSearch и VPLMN. Закроем глаза на то, что она при этом выполняет различную "фоновую" деятельность. Реакция компоненты на сообщение timeout в этих состояниях будет разной (см.рис.10.17).

Каждый миг жизни неповторим. В том числе, во многом, и для сложной программной компоненты - иначе, например, тестировщики так бы не мучались, воспроизводя ошибки системы. Однако в случае реактивных систем линии жизни программных компонент из бесконечных или очень длинных делаются относительно небольшими. Различные состояния компоненты факторизуют ее поведение, отбрасывая несущественные отличия и "склеивая", отождествляя, разные отрезки жизни, делая множество состояний из бесконечного конечным и обозримым. Например, пользователь мобильной трубки ввел правильный PUK и тогда он снова начинает вводить PIN. Компонента Main "не помнит", что все идет по второму кругу. Или по третьему, и так далее. Для нее все происходит так, как будто трубку только что включили.

В UML 2.0 у состояния возможны следующие атрибуты:

  • имя;
  • деятельность по входу ;
  • деятельность по выходу ;
  • деятельность в состоянии ;
  • внутренний переход.

Примеры имен состояний можно увидеть на рис.10.11- PLMNSearch (поиск мобильной трубкой своей сети) и WaitingForPIN (ожидание мобильной станцией ввода пользователем PIN ). Если генерировать по диаграмме конечных автоматов программный код, то в диаграммах лучше использовать англоязычные идентификаторы, допустимые в целевом языке программирования.


Рис. 10.11. Примеры состояний

 

Деятельность по входу (entry activity) - это работа, выполняемая компонентой в данном состоянии сразу после входа, независимо от того перехода, посредством которого компонента попала в это состояние. Здесь может быть выполнено одно или несколько действий, но деятельность по входу не должна быть длительной, так как она не может быть прервана внешним событием. Пример деятельности по входу представлен на рис.10.11. Там при входе в состояние PLMNSearch запускается таймер T, ограничивающий максимальное пребывание компоненты в этом состоянии временным интервалом 0.5 секунд (именно на этот временной интервал таймер T установлен, как будет рассказано ниже, при подробном обсуждении поведения компоненты Main ).

Деятельность по выходу (exit activity) - это работа, выполняемая в данном состоянии непосредственно перед выходом из него, независимо от того перехода, посредством которого компонента покидает это состояние. Здесь может быть выполнено одно или несколько действий, но пребывание компоненты здесь не должно быть длительным, так как деятельность по выходу не может быть прервана внешним событием. Пример деятельности по выходу представлен на рис.10.11. Там при выходе из состояния PLMNSearch происходит остановка таймера T, так как этот таймер нужен для ограничения времени пребываний компоненты только в данном состоянии.

Деятельность в состоянии (do activity) - это работа, выполняемая компонентой, когда она находится в данном состоянии. Деятельность в состоянии может быть прервана событием, которое компонента обрабатывает в данном состоянии. С помощью данной конструкции удобно моделировать фоновую деятельность в состоянии. Деятельность в состоянии, как правило, выражается с помощью вызова операции компоненты. Она не прерывается внутренним переходом. Пример представлен на рис.10.11. Там в состоянии PLNMSearch запускается операция PLMN_Search(), которая осуществляет поиск своей сети для данной мобильной трубки.

Внутренний переход (internal transition) - это переход, который происходит внутри состояния: компонента обрабатывает событие, не выходя из состояния. В результате выполнения такого перехода не выполняется деятельность по входу/выходу. Этот переход определяется в виде текста внутри состояния, а не в виде линии со стрелкой, т. к., собственно, перехода никуда не происходит. Пример представлен на рис.10.11. В состоянии WaitingForPIN, после ввода владельцем трубки PIN и при условии, что этот PIN неверен и число сделанных попыток не превосходит трех, компонента остается в этом же состоянии. Если бы произошел выход и повторный вход в состояние WatingForPIN, то счетчик попыток (переменная n ) был бы обнулен.

Cобытие

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

  • изменение значения некоторого булевского выражения (change event);
  • срабатывание некоторого таймера, то есть прием специального сообщения (timeout);
  • получение компонентой сообщения (signal event);
  • вызов операции компоненты извне через ее интерфейс (call event);
  • обращение извне к переменным компоненты через ее интерфейс.

 

Переход

Конструкция конечного автомата, которая определяет переход компоненты из одного состояния в другое в связи с возникновением определенного события, так и называется - переход (transition). Он инициируется событием, представляет собой цепочку действий (actions) по обработке данного события и завершается новым состоянием компоненты. Пример показан на рис.10.12.


Рис. 10.12. Пример перехода

 

После того как компонента Main, находясь в состоянии WaitingForPIN, получила сообщение PIN, она переходит в состояние PLMNSearch (поиск сети), совершая в переходе единственное действие - посылку сообщения Search_for_PLMN компоненте UserDriver, чтобы та могла показать соответствующую картинку на дисплее телефона.

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

Выход компоненты из состояния может зависеть не только от события, но и от значения охраняющего условия (guarded condition) - логического выражения, которое связано с переходом и проверяется перед тем, как компонента войдет в переход. Если охраняющее условие не выполнено (имеет значение "ложь"), то перехода не происходит. Так, например, на рис.10.13 показано, что переход в состояние PLMNSearch выполняется не просто после получения PIN, а только после его проверки и в случае, когда он правильный. Вызов функции CheckPIN(), возвращающей булевское значение, выступает здесь в роли охраняющего условия.


Рис. 10.13. Пример охраняющего условия

 

Действия в переходе не специфицируются в UML - согласно стандарту это некоторая последовательность выражений (скорее всего, на языке реализации). Тем не менее будем отличать следующие виды действий:

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

Последний вид действия авторы UML все-таки "вытянули" на модельный уровень, назвав эту конструкцию выбор (choice). Пример показан на рис.10.14.


Рис. 10.14. Пример конструкции выбор

 

После того, как пользователь мобильного телефона ввел PIN, возможно три ситуации: (i) PIN введен правильно; (ii) PIN введен неправильно и число попыток не превышает трех; (iii) PIN введен неправильно и число попыток равно трем. Первая и третья ситуация специфицированы с применением конструкции выбора, а вторая определена с помощью внутреннего перехода (и поэтому в конструкции "выбор" всего две ветки).

С помощью конструкции "выбор" можно создавать сложные переходы. Охраняющее условие каждой такой конструкции будет вычисляться в тот момент, когда до него дойдет поток управления (динамический выбор). Это дает возможность охраняющим условиям зависеть от предшествующего потока управления в переходе.

 

Таймер

При моделировании систем реального времени очень важной является конструкция таймер (timer). Она позволяет наложить временные ограничения на исполнение тех или иных действий, ожидание тех или иных событий и пр. При получении сообщения timeout (срабатывание таймера) компонента "понимает", что время какого-то ограничения истекло и надо соответствующим образом действовать, прервав предыдущую активность (или неактивность, если компонента ожидала какого-то события).

У таймера есть следующие операции:

  • установить - позволяет установить конкретный таймер на определенное время, например, на 0,5 секунд;
  • запустить - таймер начинает "тикать";
  • остановить - запущенный таймер останавливается; это нужно, когда ожидаемое событие или выполняемые действия уложились в заданный временной интервал и поэтому теперь нет необходимости дожидаться события timeout; при следующем после остановки запуске таймер стартует с нулевой временной отметки.

Событие "таймер Т истек" (получение компонентой сообщения timeout с именем истекшего таймера Т ) означает, что с момента старта Т времени прошло ровно столько, на какое он был установлен. Обработчики события timeout должны быть описаны в поведении компоненты.

На рис.10.15 приводится пример работы с таймером. При входе в состояние VPLMN (мобильной трубке доступен ограниченный сервис некоторой чужой станции, так как своя не найдена) таймер T стартует (установлен на временной интервал в 0,5 секунд он был когда-то раньше). Пробыв в этом состоянии положенное время (то есть те самые 0,5 секунд), трубка снова начинает поиск своей сети - а вдруг абонент, передвигаясь, снова оказался в зоне ее доступа? При выходе из данного состояния таймер останавливается - это сделано для обработки ситуаций, когда выход из данного состояния происходит не по timeout, а по другому событию. Будем считать, что остановка истекшего таймера также является корректной - при этом ничего не происходит, но такая возможность позволяет уменьшить сложность спецификации.

Рис. 10.15. Пример работы с таймером

 

Таймер отсутствует в UML и взят из языка SDL. Вместо него в UML есть операции со временем, но их удобнее использовать на диаграммах последовательностей. Таймер и другие конструкции конечного автомата, которые взяты из SDL и использованы в примере, можно выразить с помощью extention-механизма UML, специально созданного для подобных расширений языка.

 

Групповые состояния

Рассмотрим один интересный вид состояния, который не вошел в UML, но был в языке SDL - групповые состояния.

Эти состояния применяются для того, чтобы в конечном автомате компактно определить одинаковые реакции компоненты на ряд событий в нескольких разных состояниях. Используется символ состояния, внутри которого перечисляются все состояния, которые таким образом объединяются. Далее для них определяются общие события и переходы. Если вместо имени состояния вводится символ "*", то это означает, что определяется набор общих переходов для всех состояний данной компоненты.

На рис.10.16а показано, что компонента Main в состояниях WaitingForPIN, WaitingForPUK, ServiceBlocked, VPLMN, Idle одинаково реагирует на запрос по обработке экстренного вызова. При получении сообщения EmergencyCall она переходит в состояние ECProcessing, где происходит обработка этого вызова. После этого происходит возврат в исходное состояние. Этот возврат - не вполне обычный переход, так как, фактически, групповое состояние - это псевдосостояние. Перейти в него, как в обычное состояние, нельзя, в него можно лишь вернуться, как показано в нашем примере. Этот возврат означает, что компонента оказывается в том же состоянии, из которого она перешла в состояние ECProcessing. Реализация всего этого в программном коде будет представлена ниже.

На рис.10.16б представлен переход из группового состояния-звездочки: в любом состоянии компонента Main должна обработать сообщение о выключении трубки (пользователь нажал на кнопку "выключить").

Рис. 10.16. Переход из группового состояния

Групповые состояния - это еще один вид "синтаксического сахара": они могут быть выражены другими конструкциями языка и вводятся исключительно для удобства, а не для увеличения выразительной силы UML.

 

Реализационная диаграмма конечных автоматов

На рис.10.17 представлен формальный вариант спецификации поведения компоненты Main, по которому осуществляется генерация исполняемого кода.


Рис. 10.17. Полная спецификация поведения компоненты Main

 

Эта диаграмма получается из диаграммы, представленной на рис.10.8, путем выполнения следующих действий:

  • замена всех русских идентификаторов на английские; в частности, термин "сеть" заменен на стандартное сокращение PLMN (Public Land Mobile Network) ;
  • усложнен переход - вместо неформальной подписи на русском языке используются следующие модельные конструкции: получение сообщения, охраняющие условия, посылка сообщений, а также выбор;
  • в состояния введена (разумеется, там, где нужно) деятельность по входу/выходу и в состоянии, внутренние переходы ;
  • введен таймер с именем T ;
  • синтаксис выражений, вызовов процедур и пр. текстовых вставок приведен к формату целевого языка, в который будет производиться генерация - языку С

 

Генерация кода

В конце этого раздела представлен код на языке С, который автоматически сгенерирован по диаграмме с рис.10.17. Сделаю несколько оговорок относительно этого кода.

  1. Результаты генерации представлены в одном файле, хотя на самом деле файлов должно быть намного больше. Вот, например, секции, помеченные примечаниями "//Main interface" и "//UD interface". Они описывают сгенерированный код для UML-интерфейсов Main и UD, представленных на рис.10.9. Очевидно, что они должны быть доступны и в С-файле, который содержит сгенерированный код для компоненты UserDriver. Поэтому содержимое этих секций должно находиться в отдельных h-файлах, которые присоединяются к нужным с-файлам с помощью include-директивы языка C.
  2. Нужно честно признать, что представленный ниже код работать не будет. И не только потому, что его нужно дополнить сгенерированным кодом для компоненты UserDriver. Также требуется реализовать и многочисленные процедуры поддержки, в частности, SendMessage() для посылки сообщений, GetEvent() для получения очередного события, таймерные операции. И, наконец, пример не дописан, так как не реализованы процедуры CheckPin(), CheckPUK() и некоторые другие.

Однако все эти "недостатки" делают сгенерированный код более компактным и удобным в иллюстративных целях.

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

  1. То, что генерируется по UML-моделям: интерфейсы Main и UD, внутренние данные и процедуры компоненты Main (см. рис.10.10) - раздел "//logical procedures and data structures".
  2. Вспомогательные данные и процедуры, которые генерируются независимо от содержимого исходной UML-спецификацией и представляют собой инфраструктуру сгенерированного кода. Описание этих сущностей помечено комментарием "//internal types, data and procedures". Сюда относятся, кроме уже отмеченных выше процедур SendMessage() и GetEvent(), также следующие процедуры: MainStateMachne() - осуществляет запуск сгенерированного конечного автомата; EventProcessing() - содержит обработку событий конечного автомата.

Конечный автомат компоненты Main работает как цикл, запускающий обработчик события (процедуру EventProcessing() ), когда компонента Main "понимает", что произошло некоторое событие, предназначенное ей для обработки. Цикл останавливается, если процедура EventProcessing() возвращает значение false. Это означает, что произошедшее событие - это получение компонентой сообщения SwitchOff, (команда выключить трубку).

По-хорошему, у компоненты должна быть еще очередь событий, в которую некий диспетчер помещает информацию о тех событиях в системе, которые ей предназначаются. А сама компонента, когда готова обрабатывать следующее событие, обращается в эту очередь. Работа с очередью скрыта в операции GetEvent(), а соответствующие структуры данных не показаны, чтобы не усложнять примера.

Теперь о процедуре EventProcessing(). Обработчик событий конечного автомата реализуется как оператор switch по состояниям компоненты Main. Каждая его ветка соответствует определенному состоянию. Внутри этих веток происходит ветвление по возможным событиям. Это - почти всегда еще один оператор switch по значениям обрабатываемых в данном состоянии сообщений. Исключением является обработка события "найдена своя станция" в соcтоянии PLMNSearch. Здесь событием является значение true переменной HomePLMN, а не присланное извне сообщение. Аналогичный способ обработки такого же типа события можно увидеть в состоянии ECProcessing.

Далее для некоторых состояний ( WaitingForPIN, WaitingForPUK ) ветки оператора switch начинаются с проверки значения логической переменной nextstate, и в случае, когда ее значение true, выполняются действия по входу для этих состояний. Это нужно, поскольку деятельность по входу при внутренних переходах не должна выполняться. Если переход внутренний, то перед его инициацией значение данной переменной устанавливается в false.

В реализации деятельности по выходу есть интересная деталь - процедура остановки таймера stop при выходе из состояний PLMNSearch и VPLMN вызывается даже в тех случаях, когда переход из состояния происходит по событию timeout. Это заложено еще в модель (см.рис.10.17), и генератор лишь повторил эту некорректность. Но, создавая такую модель, мы полагаем, что процедура stop умеет останавливать таймер, если он истек.

//Main interface

typedef enum ToMain {PIN, EmergencyCall,TimeoutT,PUK, SwitchOn, SwitchOff};

 

//UD interface

typedef enum ToUserDriver{ToPin, CallProcessing, VPLMN, HomePLMN, Blocked, ToPUK, Search_for_PLMN};

 

// timer definition

typedef int timer;

void start(timer);

void set (timer, float);

void stop (timer);

 

// logical procedures and data structures

int n;

int k;

bool V_PLMN;

bool Home_PLMN;

timer T;

bool CallProcessingFinished;

bool CheckPIN();

bool CheckPUK();

void PLMN_Search();

void EC_Processing();

 

 

//internal types, data and procedures

typedef enum State {WatingForPIN,WatingForPUK, PLMNSearch, ECProcessing, VPLMN, Idle, ServiceBlocked};

ToMain input_message;

State state, prevstate;

bool nextstate = true;

void SendMessage (ToUserDriver);

bool GetEvent();

void MainStateMachine();

bool EventProcessing ();

 

 

void MainStateMachine()

{

//State Machine Initialization

bool finish = false;

 

// Transition from Start

SendMessage(ToPin);

set (T, 0.5);

state = WatingForPIN;

 

//State Machne Run

while (!finish)

if (GetEvent()) finish = EventProcessing();

}

 

bool EventProcessing (){

bool f = false;

switch (state){

 

case WatingForPIN:

if (nextstate) n = 0;

nextstate = true;

switch (input_message) {

case PIN:

if (CheckPIN()) {SendMessage (Search_for_PLMN);state = PLMNSearch;}

else if (n==3) {SendMessage(ToPUK); state = WatingForPUK;}

else {n++; nextstate = false;}

break;

case EmergencyCall: SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: f = true; break;}

break;

 

case WatingForPUK:

if (nextstate)k = 0;

nextstate = true;

switch (input_message){

case PUK:

if (CheckPUK()) state = WatingForPIN;

else if (k< 10){k++; nextstate = false;}

else if (k == 10) {SendMessage(Blocked); state = ServiceBlocked;}

break;

case EmergencyCall: SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: f = true; break;}

break;

 

case PLMNSearch:

nextstate = true;

start(T);

PLMN_Search();

if (Home_PLMN) {SendMessage (HomePLMN); stop(T); state = Idle; break;}

switch (input_message){

case TimeoutT: stop(T);

if (V_PLMN) {SendMessage(VPLMN); state =VPLMN;}

else state=PLMNSearch;

break;

case EmergencyCall: stop(T); SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: stop(T);f = true; break;}

break;

 

case VPLMN:

nextstate = true;

start(T);

switch (input_message){

case TimeoutT: stop(T); state=PLMNSearch; break;

case EmergencyCall: stop(T); SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: stop(T); f = true; break;}

break;

 

case ECProcessing:

nextstate = true;

CallProcessingFinished = false;

EC_Processing();

if (CallProcessingFinished) state = prevstate;

else if (input_message == SwitchOff) f = true;

break;

 

case Idle:

nextstate = true;

switch (input_message){

case EmergencyCall: SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: f = true; break;}

break;

 

case ServiceBlocked:

nextstate = true;

switch (input_message){

case EmergencyCall: SendMessage(CallProcessing);

prevstate = state; state = ECProcessing; break;

case SwitchOff: f = true; break;}

break;

}

return f;

}

 


<== предыдущая страница | следующая страница ==>
Реактивные системы | Лекция 11. Визуальное моделирование бизнес-процессов

Дата добавления: 2014-02-26; просмотров: 611; Нарушение авторских прав




Мы поможем в написании ваших работ!
lektsiopedia.org - Лекциопедия - 2013 год. | Страница сгенерирована за: 0.055 сек.