相比起来,Consumption联邦与Production联邦很相似,都采用NER方式推进时间,其lookahead也都是0.01。
程序结构也非常相似。
Consumption联邦也由多个java文件组成。包括:Consumption.java, ConsumptionFrame.java,ConsumptionInternalError.java, ConsumptionNames.java, FedAmbImpl.java (consumption)。
其中,frame是GUI类,FedAmbImpl包括所有回调函数。
--------------------------------------------------------------------------------------------------------------------------------------
主函数很简单
public static void main(String[] args) {
Properties props = parseArgs(args);
loadProperties(props);
Consumption consumption = new Consumption(props);
consumption.mainThread();
}
主要功能是从命令行或者配置文件中读取相关参数,产生Consumption对象,运行mainThread线程
---------------------------------------------------------------------------------------------------------
主要的功能都在mainThread函数中
(1)取得相关配置信息,判断是否有federation execution实例运行,没有则创建,然后加入join
(2)设置时间受限和时间调节。这里首先设置了时间受限,同时在设置时间受限和时间调节时,使用了barrier机制来协调各个线程(barrier机制在例子中多次使用,这里不讨论其细节)。
(3)获取相关对象类,属性,交互类的handle,存储下来以备后续使用。--getHandles();
(4)发布对象类及其相关属性,
//publish Serving position because we'll update it
_rti.publishObjectClass(_ServingClass, _positionAttributeAsSet);
//publish Diner class because we register them
_rti.publishObjectClass(_DinerClass, _DinerAttributes);
//publish the interaction because it's our job to send it
_rti.publishInteractionClass(_SimulationEndsClass);
显然, 发布对象包括Serving类及其position属性,Dinner类及其属性, 发布SimulationEnds交互类。注意,Serving对象类被多个联邦发布,consumption联邦发布Serving对象类,因为该联邦将从Transport联邦获取Serving对象类某实例的position属性的所有权。
(5)订阅对象类及其相关属性,
_rti.subscribeObjectClassAttributes(_BoatClass, _BoatAttributes);
_rti.subscribeObjectClassAttributes(_ServingClass, _positionAttributeAsSet);
订阅包括Boat对象类及其属性,Serving对象类及其属性。
(6)处理第一个同步点ReadyToPolulate,发出同步点已经achieved请求。使用barrier机制阻塞线程,结束阻塞后输出已经同步信息。
(7)调用makeInitialInstances函数,根据numberofDiner进行循环,循环体如下:
{
构造dinername和position,获取dinerHandle(同时注册diner对象类的实例),将diner对象加入local table中
_dinerTable.add(
dinerHandle,
dinerName,
position,
Diner.LOOKING_FOR_FOOD,
"",
0);
更新相应对象类实例的属性值:
LogicalTime sendTime = new LogicalTimeDouble(0.0);
sendTime.setTo(_logicalTime);
sendTime.increaseBy(_lookahead);
EventRetractionHandle erh =
_rti.updateAttributeValues(dinerHandle, sa, null, sendTime);
填充相应的_consumptionTimes[serial]数组元素
} //循环结束
(8)处理第二个同步点ReadyToRun,发出同步点已经achieved请求。使用barrier机制阻塞线程,结束阻塞后输出已经在该同步点同步的信息。
(9)调用rti函数enableAsynchronousDelivery,目的是instructs the LRC to begin delivering receive-ordered events to the federate even while no time-advancement service is in progress,其实就是consumption这个时间受限联邦成员要求在时间批准状态下也能接收RO事件。
(10)进入时间推进的主循环。循环结束条件是该联邦收到simulationEnds交互。基本的消息循环流程:consumption联邦收到的所有RTI的回调都会进入callbackQueue排队。然后在消息循环里面逐一取出消息来处理。
下面是主循环代码:
timeLoop:
while (!_simulationEndsReceived) {
_userInterface.setTimeStateAdvancing();
LogicalTime timeToMoveTo = _internalQueue.getTimeAtHead();
//_userInterface.post("NER to " + timeToMoveTo);
_rti.nextEventRequest(timeToMoveTo);
//process all the events & callbacks we receive from the RTI
boolean wasTimeAdvanceGrant;
do {
Callback callback = _callbackQueue.dequeue();
wasTimeAdvanceGrant = callback.dispatch();
//_userInterface.post("After dispatch " + _logicalTime);
} while (!wasTimeAdvanceGrant);
updateInternalStateAtNewTime();
if (_simulationEndsReceived) break timeLoop;
//process callbacks not requiring advance while in granted state
while (!_dinerTable.isTimeAdvanceRequired()) {
Callback callback = _callbackQueue.dequeue();
callback.dispatch();
}
}
主循环流程解释如下:
while(没有收到simulationEnds交互)
{
界面显示联邦开始时间推进;
从_internalQueue队列中取出队头事件所包含的时间(对consumption联邦而言,只有获得某Serving的所有权之后,才会在_internalQueue中插入一个FinishEatingSushiEvent,这个evnet所附带的时间是_logicalTime+某diner吃完这个sush的平均时间);
请求时间推进NER到上一条语句所取出的时间上,对consumption联邦而言,其实就是取出某diner吃完一个sushi后的logicTime时间。
do{
从callbackQueue中取出一个事件,返回给callback对象;
调用callback对象的dispatch函数,返回一个布尔量wasTimeAdvanceGrant
判断是否收到_simulationEnds交互,如果收到,退出循环;
while (!wasTimeAdvanceGrant);
————————————————————————————————————————————————checkInternalQueue()函数
从internalQueue中取出(并删除)所有小于等于当前时间的事件处理掉,此例中就是取出可能的FinishEatingSushiEvent,并开始调用RTI函数attributeOwnershipAcquisition请求删除该Serving实例:
_rti.attributeOwnershipAcquisition(
_dinerTable.getServing(_diner),
_privilegeToDeleteObjectAttributeAsSet,
null);
后面在AOAN的dispatch函数中,判断ownership是否得到,如果得到,则开始删除该Serving
else if (_attributes.equals(_privilegeToDeleteObjectAttributeAsSet)) {
finishDestroyingServing();
}
并更新某diner的状态; --checkInternalQueue()函数
————————————————————————————————————————————————checkInternalQueue()函数
更新_dinerTable中的diner对象类实例信息,并调用rti.updateAttributeValues(diner._handle, sa, null, sendTime);在联邦中更新diner对象实例信息。
根据当前_servings中所有的sushi信息,发送updateAttributeValues请求或者直接删除对象实例_rti.deleteObjectInstance(serving._handle, null, sendTime);
判断是否消耗了足够多的sushi,如果足够多,则发出SimulationEnds交互。
}
(11)处理第三个同步点ReadyToResign,发出同步点已经achieved请求。使用barrier机制阻塞线程,结束阻塞后输出已经在该同步点同步的信息。然后结束该联邦的运行。
---------------------------------------------------------------------------------------------------------------------------
下面从consumption运行的log文件来进行动态分析
RTIambassador created
Federation execution restaurant_1 already exists.
Joined as federate 5
Enabling time constraint...
...constraint enabled at time<0.0>
Enabling time regulation...
...regulation enabled at time<0.0>
Waiting for ReadyToPopulate...
�5.10)startRegistrationForObjectClass:3
�5.12)turnInteractionsOn:4
�5.10)startRegistrationForObjectClass:7
...federation synchronized.
Waiting for ReadyToRun...
...federation synchronized.
//之前无话,跟前面的联邦运行情况基本相同,尤其跟production基本类似。
NER to time<INF>
// 进入时间推进循环,明显看到刚开始时,_internalQueue中没有事件,因此返回的推进时间是INF,即寻求推进到结束时间
This is DiscoverObjectInstanceCallback's dispatch B_3_0 105
Discovered Boat 105(B_3_0)
This is DiscoverObjectInstanceCallback's dispatch B_3_1 113
Discovered Boat 113(B_3_1)
This is DiscoverObjectInstanceCallback's dispatch B_3_2 114
Discovered Boat 114(B_3_2)
This is DiscoverObjectInstanceCallback's dispatch B_3_3 115
Discovered Boat 115(B_3_3)
This is DiscoverObjectInstanceCallback's dispatch B_3_4 116
Discovered Boat 116(B_3_4)
This is DiscoverObjectInstanceCallback's dispatch B_3_5 118
Discovered Boat 118(B_3_5)
This is DiscoverObjectInstanceCallback's dispatch B_3_6 120
Discovered Boat 120(B_3_6)
This is DiscoverObjectInstanceCallback's dispatch B_3_7 121
Discovered