本文从宏观角度讲解The ONE事件是如何组织的,即由EventQueueHandle
类处理所有事件,将所有事件组织成一个队列,每个update internal
处理队列的所有事件。
1. The ONE事件
1.1 事件组织
最开始以为The ONE会为每个DTNHost
设置一个事件队列,但实际不是,而是全局维持一个事件队列链表(仿真与现实的差距!),由EventQueueHandle
类处理所有事件。
EventQueueHandle
类成员变量queues
维护着整个仿真的所有事件,事件可以是:消息事件产生器MessageEventGenerator
、连接事件ConnectionEvent
、消息事件MessageEvent
(包含消息创建、转发、删除)。The ONE所有事件(消息产生器事件、外部消息事件、连接事件)是这样组织的(队列嵌套队列):
图1 The ONE事件组织
1.2 事件
EventQueueHandler
类维持着一个EventQueue
接口类的列表,用具体实现抽象方法的类实例化接口类,实现多态,如下:
private List<EventQueue> queues;
目前只有外部事件队列ExternalEventsQueue
和消息事件队列MessageEventGenerator
实现了EventQueue
接口,所以EventQueueHandler
只能处理这两种事件队列。ExternalEventsQueue
类成员变量queue
将外部事件(ExternalEvent
)组织成一个队列,如下:
private List<ExternalEvent> queue;
该队列包含ConnectionEvent
和MessageEvent
(包含消息创建、转发、删除)。The ONE所有事件的类图关系如下:
图2 The ONE事件类图
2. 事件处理
2.1 EventQueueHandler
事件队列处理EventQueueHandler
在仿真初始化时创建,调用路径:main(DTNSim)—> DTNSimTextUI().start() –> initModel(DTNSimUI) –> SimScenario.getInstance –> SimScenario
构造函数,相关的源代码如下:
/*** 创建EventQueueHandler ***/ private EventQueueHandler eqHandler; //SimScenario.java 私有成员变量 //在SimScenario()构造函数中 this.eqHandler = new EventQueueHandler(); //创建EventQueueHandler this.world = new World(hosts, worldSizeX, worldSizeY, updateInterval, updateListeners, simulateConnections, eqHandler.getEventQueues()); //eqHandler.getEventQueues() //SimScenario.java public List<EventQueue> getExternalEvents() { return this.eqHandler.getEventQueues(); //返回EventQueue接口类型的列表 } //World.java 包含所有节点,更新节点的位置和连接状态 this.eventQueues = eventQueues; //World构造函数中 private EventQueue nextEventQueue; //World.java 私有成员变量
2.2 EventQueueHandler构造函数
The ONE初始化时,创建场景SimScenario()
会创建EventQueueHandler
一个实例。EventQueueHandler
构造函数读取创建外部事件和消息产生器事件(如果有的话),其源代码如下:
public EventQueueHandler() { Settings settings = new Settings(SETTINGS_NAMESPACE); //SETTINGS_NAMESPACE = "Events"; int nrof = settings.getInt(NROF_SETTING); this.queues = new ArrayList<EventQueue>(); for (int i=1; i <= nrof; i++) { Settings s = new Settings(SETTINGS_NAMESPACE + i); /*********** 外部事件 ***********/ if (s.contains(PATH_SETTING)) { int preload = 0; String path = ""; if (s.contains(PRELOAD_SETTING)) { preload = s.getInt(PRELOAD_SETTING); } path = s.getSetting(PATH_SETTING); queues.add(new ExternalEventsQueue(path, preload)); //创建外部事件,并加入到queues } /*********** 消息产生器事件 ***********/ else if (s.contains(CLASS_SETTING)) { String className = CLASS_PACKAGE + "." + s.getSetting(CLASS_SETTING); EventQueue eq = (EventQueue)s.createIntializedObject(className); queues.add(eq); } } }
2.3 事件处理
各种类型事件都有相应的事件处理函数processEvent
,当事件被触发时,就调用相应的该事件的processEvent
(这点类似于钩子函数)。以MessageCreateEvent
为例,其processEvent
函数源码如下:
public void processEvent(World world) { DTNHost to = world.getNodeByAddress(this.toAddr); DTNHost from = world.getNodeByAddress(this.fromAddr); Message m = new Message(from, to, this.id, this.size); m.setResponseSize(this.responseSize); from.createNewMessage(m); //创建消息 }
关于事件被触发的过程,请移步博文《The ONE使用笔记:连接事件ConnectionEvent读取与处理》。
赞赏微信赞赏
支付宝赞赏
Awesome site you have here but I was wondering if you knew of any message boards that cover the
same topics discussed here? I’d really love to be a part of group where I can get responses from other knowledgeable people that
share the same interest. If you have any suggestions, please
let me know. Thanks!
You might be interested in this.
theONE — User community for the ONE simulator
Pingback: The ONE使用笔记:深入源码理解消息创建过程 | Spark & Shine
Pingback: The ONE使用笔记:目录 | Spark & Shine
Pingback: The ONE使用笔记:连接事件ConnectionEvent读取与处理 | Spark & Shine