Диаграмма состояний Rhapsody C++ - событие (кажется, работает) и запущенная операция (кажется, ничего не делает)

Я использую Rhapsody 8.2.1 и просто изучаю некоторые основы.

У меня он компилируется (с MSVC 2012), генерирует код и работает. Для начала у меня был класс counter с одним атрибутом int m_count с конструктором, выводящим "hello" и диаграмму состояний с одним состоянием start с переходом к нему по умолчанию - транзакция по умолчанию устанавливает m_count = 3. start::stateEntry() действие, которое выполняет printf("start - stateEntry m_count = %d\r\n", m_count);.

Итак, затем я добавил событие таймера, переходящее из состояния start --> start каждую секунду. Что делает m_count -= 1

Итак... как и следовало ожидать, когда я запускаю это, я получаю:

start - stateEntry m_count = 3
start - stateEntry m_count = 2
start - stateEntry m_count = 1
start - stateEntry m_count = 0
start - stateEntry m_count = -1
      etc...

Теперь я, когда m_count == 0 хочу перейти в новое состояние done. Поэтому для этого я добавляю новое состояние и соединяю два состояния с переходом состояния, идущим из start --> done. Я называю переход состояния evTrigger (как я видел в туториале) и нажимаю ctrl+enter. Это приводит к добавлению:

  • Новое событие под названием evTrigger
  • Новая активируемая операция с именем counter::evTrigger() (член класса counter).

Когда я открываю переход, «Триггер» говорит evTrigger in Default — так что я предполагаю, что это относится к событию, а не к запущенной операции.

Теперь я пытаюсь его использовать, я добавляю следующий код в действие входа в состояние start:

if (m_count <= 0)
{
    GEN(evTrigger());
}

А в записи состояния done ставлю код: printf("stateEntry - Done!\r\n");

Итак, это работает - я получаю:

start - stateEntry m_count = 3
start - stateEntry m_count = 2
start - stateEntry m_count = 1
start - stateEntry m_count = 0
stateEntry - done!

Но я не могу использовать созданную для меня триггерную операцию под названием evTrigger(). Почему бы нет? Если я вызову evTrigger() вместо GEN(evTrigger()); он компилируется, но переход события не запускается (он продолжает обратный отсчет ниже нуля). Почему?

Затем я создаю два новых элемента для тестирования событий и триггерной операции отдельно, и я использую каждый в новом переходе от start к done, поэтому есть 3 перехода с разными триггерами:

  • новое событие evTriggerEvent
  • новая инициированная операция trTriggerOperation

Итак, диаграмма состояний выглядит так:

*
|  /m_count = 3;
|
|       +---------+      evTrigger              +---------+
+-----> |  start  |---------------------------->|  done   |
        |---------|                             |---------|
        |         |                             |         |
        |         |      trTriggerOperation     |         |
        |         |---------------------------->|         |
        |         |                             |         |
        |         |                             |         |
        |         |      evTriggerEvent         |         |
        |         |---------------------------->|         |
        +---------+                             +---------+
          |     ^
          |     | tm(1000)/m_count -=1;
          +-----+

И действие начала входа выглядит так:

if (m_count <= 0)
{
    //GEN(evTrigger());        <----- works
    //trTriggerOperation();    <----- appears to do nothing
    //GEN(evTriggerEvent());   <----- works
}

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

GEN(evTrigger()) - Работает:

start - stateEntry m_count = 3
start - stateEntry m_count = 2
start - stateEntry m_count = 1
start - stateEntry m_count = 0
stateEntry - done!

trTriggerOperation() - Не запускает транзакцию...

start - stateEntry m_count = 3
start - stateEntry m_count = 2
start - stateEntry m_count = 1
start - stateEntry m_count = 0
start - stateEntry m_count = -1
start - stateEntry m_count = -2
      etc...

GEN(evTriggerEvent()) — работает:

start - stateEntry m_count = 3
start - stateEntry m_count = 2
start - stateEntry m_count = 1
start - stateEntry m_count = 0
stateEntry - done!

Итак, мои вопросы:

  • Почему ctrl+enter генерирует как событие, так и триггерную операцию, когда просто и событие выполняют одну и ту же работу?
  • Какова цель запускаемого действия (оно не делает того, что интуитивно должно)?
  • Как правильно использовать триггерное действие (если я делаю это неправильно)?

Обновить

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

Основная проблема в том, что документация/примеры по Rhapsody очень плохие... большинство форумов - перекати-поле, поэтому возникает дополнительный вопрос: это мертвый/умирающий продукт или что?!


person code_fodder    schedule 27.02.2018    source источник
comment
О, Рапсодия. Моя первая работа. По моей щеке течет слеза.   -  person Daniel Kamil Kozar    schedule 17.03.2018
comment
@DanielKamilKozar, лол... слезы ностальгии... или боль?   -  person code_fodder    schedule 17.03.2018
comment
Смесь того и другого, я думаю. Мне очень не нравилась сама Rhapsody (фактически поощрялось переписывать классы Rhapsody на чистом C++, где это возможно), и мне сильно недоплачивали, но я многому научился и работал с очень талантливыми людьми. Хорошие времена.   -  person Daniel Kamil Kozar    schedule 17.03.2018


Ответы (1)


Ctrl+Enter просто выводит вас из режима редактирования, когда вы вводите текст поверх перехода/состояния/любого другого графического элемента — это не должно создавать триггерные операции.

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

Вы вызываете триггерную операцию так же, как вы вызываете примитивную операцию (например, myInstance->myTrigOp(myArgValue)). Триггерные операции могут иметь аргументы и могут возвращать значение, однако существует специальный способ доступа к аргументам и установки возвращаемого значения из действий конечного автомата.

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

person Eldad Palachi    schedule 05.03.2018
comment
Спасибо за информацию :) it is not supposed to create triggered operations - а ведь так и есть!. You call a triggered operation just like you call a primitive operation, но, как и в моем примере, это не сработало - и, как я уже упоминал, справочная система Rhapsody в лучшем случае плохая. - person code_fodder; 06.03.2018