事件驱动模拟类 我正在用Bjarne Stroustrup的C++编程语言进行一些练习。我被第12章末尾的问题11弄糊涂了: (*5)设计并实现一个用于编写事件驱动模拟的库。提示:。。。task类的对象应该能够保存其状态并恢复该状态,以便它可以作为协同程序运行。特定任务可以定义为从任务派生的类的对象。任务要执行的程序可以定义为虚拟函数。。。应该有一个调度器来实现虚拟时间的概念。。。这些任务需要沟通。为此设计一个类队列。。。

事件驱动模拟类 我正在用Bjarne Stroustrup的C++编程语言进行一些练习。我被第12章末尾的问题11弄糊涂了: (*5)设计并实现一个用于编写事件驱动模拟的库。提示:。。。task类的对象应该能够保存其状态并恢复该状态,以便它可以作为协同程序运行。特定任务可以定义为从任务派生的类的对象。任务要执行的程序可以定义为虚拟函数。。。应该有一个调度器来实现虚拟时间的概念。。。这些任务需要沟通。为此设计一个类队列。。。,c++,simulation,event-driven,C++,Simulation,Event Driven,我不确定这到底是什么要求。任务是一个单独的线程吗?(据我所知,不需要系统调用就不能创建一个新线程,因为这是一本关于C++的书,我不相信这是意图)。没有中断,如何启动和停止运行函数?我假设这将涉及忙等待(也就是说,不断循环并检查一个条件),尽管我看不出如何将其应用于可能在一段时间内不会终止的函数(例如,如果它包含无限循环) < > > >编辑:请参阅下面的帖子,请提供更多信息。 < P>(我不是C++ DeV)< /P> 这可能意味着您需要创建一个类任务(如事件中的任务),该类任务主要由回调函数指

我不确定这到底是什么要求。任务是一个单独的线程吗?(据我所知,不需要系统调用就不能创建一个新线程,因为这是一本关于C++的书,我不相信这是意图)。没有中断,如何启动和停止运行函数?我假设这将涉及忙等待(也就是说,不断循环并检查一个条件),尽管我看不出如何将其应用于可能在一段时间内不会终止的函数(例如,如果它包含无限循环)

< > > >编辑:请参阅下面的帖子,请提供更多信息。

< P>(我不是C++ DeV)< /P> 这可能意味着您需要创建一个类任务(如事件中的任务),该类任务主要由回调函数指针和计划时间组成,并且可以存储在调度程序类的列表中,而调度程序类基本上应该跟踪时间计数器,并在时间到达时调用每个任务的函数。这些任务应由仿真对象创建


如果您需要离散模拟方面的帮助,请继续编辑问题。

我觉得这个练习要求您实现一个协作式多任务调度程序。调度器在虚拟时间(您定义/实现的任何级别的时间标记)中运行,根据队列选择要运行的任务(请注意,您需要实现的描述),当当前任务完成时,调度器选择下一个任务并开始运行

提示:

是对随附的旧协作多任务库的引用(您也可以在该页面下载)

如果你读了报纸,事情会变得更有意义


添加一点:

我不是一个使用过任务库的足够大的程序员。不过,我知道C++是在Stroustrup编写了一个Simula仿真之后设计的,它有许多与任务库相同的属性,所以我一直很好奇。 如果我要实现书中的练习,我可能会这样做(请注意,我没有测试过这段代码,甚至没有尝试编译它):

类调度程序{
列出任务;
公众:
无效运行()
{
while(1)//或至少在发送消息停止运行之前
for(std::list::迭代器itor=tasks.begin()
,std::list::iterator end=tasks.end()
结束
++编辑)
(*itor)->run();//是,两次取消引用
}
无效添加任务(ITask*任务)
{
任务。推回(任务);
}
};
结构ITask{
虚拟~ITask(){}
虚空运行()=0;
};
我知道人们会不同意我的一些选择。例如,为接口使用结构;但是结构的行为是默认情况下从它们继承是公共的(从类继承默认情况下是私有的),我看不到从接口私下继承有任何价值,所以为什么不将公共继承设为默认值呢

其思想是,调用ITask::run()将阻塞调度程序,直到任务到达可以中断的点,此时任务将从run方法返回,并等待调度程序再次调用run以继续。“协作式多任务处理”中的“协作”表示“任务何时可以中断”(“协同程序”通常表示“协作式多任务处理”)。一个简单的任务在其run()方法中只能做一件事,一个更复杂的任务可以实现一个状态机,并且可以使用其run()方法来确定对象当前处于什么状态,并基于该状态调用其他方法。任务必须偶尔放弃控制才能工作,因为这是“协作多任务”的定义。这也是所有现代操作系统不使用协作多任务的原因

此实现没有(1)遵循公平调度(可能会保持在任务的run()方法中花费的时钟滴答数的运行总数,并跳过相对于其他任务占用了太多时间的任务,直到其他任务“赶上”),(2)允许删除任务,甚至(3)允许停止调度程序

关于任务之间的通信,您可以考虑查看或提供灵感(“NeXSueAK”的UNIX实现”下载包括一篇论文,“NeXSueAk的实现”,讨论一个有趣的虚拟机中的消息传递。


但我相信这是Stroustrup考虑的基本框架。

以下是我对“事件驱动模拟”的理解:

  • 控制器处理事件队列,将事件安排在特定时间发生,然后在队列上执行顶部事件
  • 事件在预定时间即时发生。例如,“移动”事件将更新实体在模拟中的位置和状态,以便状态向量在当前模拟时间有效。“感知”事件必须确保所有实体的状态都在当前时间,然后使用一些数学模型来评估当前实体感知其他实体的能力。(想想莫维
    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;
    };
    
    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