【问题标题】:events happening at the same time in event-driven simulator事件驱动模拟器中同时发生的事件
【发布时间】:2016-06-21 07:12:25
【问题描述】:

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

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

当我对示例进行一些修改时,我遇到了一种情况,即当两个事件(到达、离开)同时发生(比如在时间单元 5)时,模拟器只会弹出任何内容从下面的代码 sn-p 可以看出,事件队列的顶部。

void simulation::run () {

while (! eventQueue.empty ()) {

event * nextEvent = eventQueue.top ();
eventQueue.pop ();
time = nextEvent->time;
nextEvent->processEvent ();
delete nextEvent;
  }
}

如果两个事件同时发生,我该如何强制在出发事件之前总是弹出某个事件(到达事件优先)的条件。

非常感谢任何帮助。

【问题讨论】:

  • 如果您想要可重复的模拟,“时间”事件的顺序。没有两个事件同时发生。
  • 好的,我接受你的观点。但是我仍然有一个问题,如果两个事件具有相同的时间会发生什么?我们能否确定性地说哪个事件将首先发生?通过其余的模拟。谢谢
  • 如果两个事件同时发生,这是一个错误。它不应该发生在正常运行的系统中。修好就好了。
  • 考虑这样一种情况,根据一些随机过程,许多数据包进入系统并离开系统。在这种情况下,第 (n+1) 个数据包到达事件可以与第 n 个数据包离开事件具有相同的时间。所以我无法接受这是一个错误。系统可以具有这样的属性。而且我相信事件驱动的模拟可以处理这种情况。
  • 使用 priority_queue - 按 2 个因素排序 - 从更重要的:1) 时间 2) 事件类型。就是这样。

标签: c++ event-driven event-driven-design


【解决方案1】:

我假设eventQueue 具有here 描述的类型(因为这是您问题中链接所引用的内容)。从那里,你可以读到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;
  }
}

但是...

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

namespace std {
  template <class T,
            class Container = vector<T>,
            class Compare = less<Container::value_type> >
  class priority_queue;
}

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

// 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;
  }
};

请注意,要使这是一个订单,您需要确保不会有多个同时到达(或离开)。如果(可能)存在这种情况,那么您应该(如果您想要确定性模拟)找到事件的其他属性(名称?来源?)以使它们井然有序。

你的eventQueue 会被声明为

std::priority_queue<event *, std::vector<event *>, less_event_ptr<event>> eventQueue;

【讨论】:

  • 您好丹尼尔,感谢您的回复。现在我必须处理同时发生的多个到达/离开事件。我正在检查这个,很快就会回复你。
  • 您好丹尼尔,我可以理解您提供的解决方案。我试图提出一个最小、完整且可验证的示例,以便我可以尝试您的答案并接受它。这是一个简单的代码 sn-p (gist.github.com/gmahet/2634e67e51a44d709df9),它复制了我提到的问题。你能帮我整合你的代码,这样我就可以测试它并接受你的答案。谢谢
猜你喜欢
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多