Событийный симуляционный класс - PullRequest
3 голосов
/ 16 декабря 2008

Я работаю над некоторыми упражнениями на языке программирования C ++ Бьярна Страуструпа. Меня смущает проблема 11 в конце главы 12:

(* 5) Разработка и внедрение библиотеки для написания событийно-ориентированных симуляций. Подсказка: . ... Объект задачи класса должен быть в состоянии сохранить свое состояние и восстановить это состояние, чтобы он мог работать как сопрограмма. Конкретные задачи могут быть определены как объекты классов, полученных из задачи. Программа, выполняемая задачей, может быть определена как виртуальная функция. ... Должен быть планировщик, реализующий концепцию виртуального времени. ... Задачам нужно будет общаться. Разработайте очередь классов для этого. ...

Я не уверен точно, о чем это просит. Задача - это отдельная тема? (Насколько я знаю, невозможно создать новый поток без системных вызовов, и, поскольку это книга о C ++, я не верю, что это так.) Без прерываний как можно запустить и остановить запуск? функционировать? Я предполагаю, что это будет связано с занятым ожиданием (то есть непрерывным циклом и проверкой условия), хотя я не могу понять, как это можно применить к функции, которая может не завершиться в течение некоторого времени (например, если она содержит бесконечный цикл) .

РЕДАКТИРОВАТЬ: Пожалуйста, смотрите мой пост ниже с дополнительной информацией.

Ответы [ 8 ]

5 голосов
/ 16 декабря 2008

Вот мое понимание "симуляции, управляемой событиями":

  • Контроллер обрабатывает очередь событий, планируя события, происходящие в определенное время, а затем выполняет главное событие очереди.
  • События происходят мгновенно в назначенное время. Например, событие «перемещение» будет обновлять положение и состояние объекта в моделировании, так что вектор состояния будет действительным в текущее время моделирования. «Смысловое» событие должно было бы убедиться, что все состояния сущностей находятся в текущем времени, а затем использовать некоторую математическую модель, чтобы оценить, насколько хорошо текущая сущность может воспринимать другие сущности. (Подумайте, роботы движутся по доске.)
  • Таким образом, время прогрессирует с перерывами, прыгая от события к событию. Сравните это с управляемой временем симуляцией, когда время движется дискретными шагами, а состояния всех сущностей обновляются каждый временной шаг (в большинстве моделей Simulink).
  • Затем события могут происходить с естественной скоростью. Обычно не имеет смысла пересчитывать все данные с максимальной скоростью в симуляции.

Большинство производственных событий, управляемых событиями, выполняются в одном потоке. Они могут быть сложными по своей природе, поэтому попытка синхронизировать многопоточное моделирование имеет тенденцию добавлять экспоненциальные уровни сложности. С учетом вышесказанного, существует стандарт для многопроцессного военного моделирования под названием Distributive Interactive Simulation (DIS), который использует предопределенные сообщения TCP для передачи данных между процессами.

РЕДАКТИРОВАТЬ: важно определить разницу между моделированием и симуляцией. Модель - это математическое представление системы или процесса. Симуляция строится из одной или нескольких моделей, которые выполняются в течение определенного периода времени. Опять же, управляемое событиями моделирование переходит от события к событию, в то время как управляемое временем моделирование выполняется с постоянным шагом по времени.

3 голосов
/ 16 декабря 2008

Подсказка: .

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

Если вы прочтете статью " Набор классов C ++ для совместного программирования стилей ", все станет намного понятнее.


Добавление немного:

Я не достаточно старый программист, чтобы использовать библиотеку задач. Однако я знаю, что C ++ был разработан после того, как Страуструп написал симуляцию в Simula, у которой было много тех же свойств, что и у библиотеки задач, поэтому мне всегда было интересно об этом.

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

class Scheduler {
    std::list<*ITask> tasks;
  public:
    void run()
    {
        while (1) // or at least until some message is sent to stop running
            for (std::list<*ITask>::iterator itor = tasks.begin()
                      , std::list<*ITask>::iterator end = tasks.end()
                    ; itor != end
                    ; ++itor)
                (*itor)->run(); // yes, two dereferences
    }

    void add_task(ITask* task)
    {
        tasks.push_back(task);
    }
};

struct ITask {
    virtual ~ITask() { }
    virtual void run() = 0;
};

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

Идея состоит в том, что вызовы ITask :: run () будут блокировать планировщик до тех пор, пока задача не достигнет точки, в которой она может быть прервана, и в этот момент задача вернется из метода run, и дождаться, пока планировщик вызовет бегите снова, чтобы продолжить. «Кооператив» в «кооперативной многозадачности» означает «задачи говорят, когда их можно прервать» («сопрограмма» обычно означает «кооперативная многозадачность»). Простая задача может делать только одну вещь в своем методе run (), более сложная задача может реализовывать конечный автомат и может использовать его метод run (), чтобы выяснить, в каком состоянии находится объект в настоящее время, и выполнить вызовы других методов на основе в этом состоянии. Задачи должны время от времени отказываться от управления, чтобы это работало, потому что это определение «совместной многозадачности». Это также причина, по которой все современные операционные системы не используют совместную многозадачность.

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

Что касается связи между задачами, вы можете рассмотреть вопрос о libtask Plan 9 или newsqueak Роба Пайка для вдохновения (загрузка "Реализация Newsqueak в UNIX" включает в себя статью "The Реализация "Newsqueak", в которой обсуждается передача сообщений на интересующей виртуальной машине).

Но я считаю, что это основной скелет, который имел в виду Страуструп.

2 голосов
/ 17 декабря 2008

Обобщенная структура моделирования дискретного события основана на очереди приоритетов, заданной на значении времени. В широком смысле это выглядит так:

    While (not end condition):
        Pop next event (one with the lowest time) from the priority queue
        Process that event, which may generate more events
        If a new event is generated:
            Place this on the priority queue keyed at its generated time

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

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

2 голосов
/ 16 декабря 2008

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

1 голос
/ 17 декабря 2008

Существует книга и фреймворк под названием DEMOS (моделирование дискретных событий в Simula), в которых описывается фреймворк, основанный на сопрограмме (одноименный DEMOS). Несмотря на то, что ему 30 лет или около того, DEMOS на самом деле довольно хорошая система, а Грэм Бёртвистл действительно хороший парень.

Если вы реализуете сопрограммы на C ++ (например, setjump / longjump), вам следует взглянуть на эту книгу для описания действительно, действительно элегантной структуры моделирования дискретных событий. Хотя ему 30 лет, он немного вечная классика и до сих пор имеет фанатов.

1 голос
/ 16 декабря 2008

Это ответ на комментарий titaniumdecoy к ответу SottieT812. Его слишком много для комментария, поэтому я решил сделать еще один ответ.

Это обусловлено событием в том смысле, что состояние симуляции изменяется только в ответ на событие. Например, предположим, что у вас есть два события запуск ракеты и воздействие ракеты . Когда событие launch выполнено, оно определяет, когда и где оно повлияет, и планирует событие влияние на соответствующее время. Положение ракеты не рассчитывается между пуском и ударом, хотя, вероятно, у нее будет метод, который может вызываться другими объектами для определения местоположения в конкретное время.

Это в отличие от симуляции, управляемой временем, где точное положение ракеты (и любого другого объекта в симуляции) вычисляется после каждого временного шага, скажем, 1 секунды.

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

Редактировать: Если кому-то интересно узнать больше, ознакомьтесь с документами Зимней Симуляционной Конференции

1 голос
/ 16 декабря 2008

(я не разработчик C ++)

Вероятно, это означает, что вам нужно создать класс Task (как в Event), который будет состоять в основном из указателя функции обратного вызова и запланированного времени и может быть сохранен в списке в классе Scheduler, который, в свою очередь, в основном следует отслеживать счетчик времени и вызывать функцию каждой задачи, когда придет время. Эти задачи должны быть созданы Объектами симуляции.

Если вам нужна помощь на стороне дискретного моделирования, продолжайте и отредактируйте вопрос.

0 голосов
/ 16 декабря 2008

В статье, на которую ссылается «me.yahoo.com / ...», в которой описывается класс task.h:

  1. Задачи выполняются параллельно
  2. Задание может быть приостановлено и возобновлено позже

Библиотека описана как метод мультипрограммирования.

Возможно ли это сделать без использования потоков или отдельных процессов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...