在事件驱动的模拟器中同时发生的事件

use*_*296 2 c++ event-driven-design event-driven

我一直在尝试开发一个简单的事件驱动模拟器,并从这里开始

http://stdcxx.apache.org/doc/stdlibug/11-3.html

当我正在玩这个例子进行一些修改时,我遇到了一个条件,当两个事件(到达,离开)同时发生时(比如在时间单元5),然后模拟器只是弹出顶部的任何东西事件队列可以从下面的代码片段中看到.

void simulation::run () {

while (! eventQueue.empty ()) {

event * nextEvent = eventQueue.top ();
eventQueue.pop ();
time = nextEvent->time;
nextEvent->processEvent ();
delete nextEvent;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果两个事件同时发生,我如何强制执行始终在出发事件之前弹出特定事件(首先到达事件)的条件.

任何帮助深表感谢.

Dan*_*our 5

我假设它eventQueue具有此处描述的类型(因为这是从您的问题中的链接引用的).从那里,你可以读到top()......

返回对具有最高优先级的队列中元素的常量引用

......那pop()......

从队列中删除具有最高优先级的项目.

因此,从您的问题中获取代码,最明显的方法是将具有相同时间的所有事件从队列中取出,然后才处理它们:

while (! eventQueue.empty ()) {
  event * ev = eventQueue.top (); // WHY do you have pointers here ?!?!?
  time = ev->time;
  some_container<event *> arrivals, departures;
  // Take out all events that happen "now" from the queue
  while (time == ev->time) {
    eventQueue->pop();
    if (ev->type == ARRIVAL) {
      arrivals.push_back(ev);
    } else {
      departures.push_back(ev);
    }
    ev = eventQueue->top();
  }
  // Process arrivals
  for (event * e : arrivals) {
    e->processEvent();
    delete e; // Again: WTF pointers? raw? NOT a good idea!
  }
  // Process departures
  for (event * e : departures) {
    e->processEvent();
    delete e;
  }
}
Run Code Online (Sandbox Code Playgroud)

但...

...这不是用C++处理这个问题的惯用方法.C++中的容器(至少是有序的容器)通常有一个模板参数,用于指定元素的排序方式.以下情况也是如此std::priority_queue:

namespace std {
  template <class T,
            class Container = vector<T>,
            class Compare = less<Container::value_type> >
  class priority_queue;
}
Run Code Online (Sandbox Code Playgroud)

因此,这里更好的方法是使用自定义比较函数对象在所有事件之间建立顺序:

// sigh ... pointers ... raw pointers ... just WHY???!?
template<typename Event>
struct less_event_ptr {
  std::less<time_type> time_compare; // time_type hopefully is self-describing ...
  bool operator()(Event * lhs, Event * rhs) const {
    if (time_compare(lhs->time, rhs>-time)) {
      return true;
    }
    if (time_compare(rhs->time, lhs->time)) {
      return false;
    }
    if (lhs->type == ARRIVAL && rhs->type == DEPARTURE) {
      return true;
    }
    return false;
  }
};
Run Code Online (Sandbox Code Playgroud)

请注意,要将此作为订单,您需要确保不会同时有多个到达(或离开).如果有(可能)这样的情况,那么你应该(如果你想要一个确定性模拟)找到事件的其他属性(名称?来源?)以使它们按顺序排列.

eventQueue然后你会被宣布为

std::priority_queue<event *, std::vector<event *>, less_event_ptr<event>> eventQueue;
Run Code Online (Sandbox Code Playgroud)