Класс событийно-ориентированного моделирования

StackOverflow https://stackoverflow.com/questions/369948

  •  21-08-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

Намекать:<задача.h>.

— это отсылка к старой библиотеке кооперативной многозадачности, поставляемой вместе с ранние версии 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 или Новости Роба Пайка для вдохновения (загрузка «UNIX-реализация Newsqueak» включает в себя статью «Реализация Newsqueak», в которой обсуждается передача сообщений в интересной виртуальной машине).

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

Другие советы

Вот мое понимание «моделирования, управляемого событиями»:

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

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

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

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

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

    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, поместить задание в очередь для следующего шага).Это несколько проще программировать, поскольку ресурсы захвата обрабатываются с помощью примитивов синхронизации, подобных семафорам.Задания и примитивы синхронизации генерируют события и помещают их в очередь в фоновом режиме.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top