@@ -68,16 +68,15 @@ public final class DefaultPassengerEngine implements PassengerEngine, PassengerR
68
68
69
69
//accessed in doSimStep() and handleDeparture() (no need to sync)
70
70
private final Map <Id <Request >, MobsimPassengerAgent > activePassengers = new HashMap <>();
71
-
71
+
72
72
// holds vehicle stop activities for requests that have not arrived at departure point yet
73
73
private final Map <Id <Request >, PassengerPickupActivity > waitingForPassenger = new HashMap <>();
74
74
75
75
//accessed in doSimStep() and handleEvent() (potential data races)
76
76
private final Queue <PassengerRequestRejectedEvent > rejectedRequestsEvents = new ConcurrentLinkedQueue <>();
77
77
78
- DefaultPassengerEngine (String mode , EventsManager eventsManager , MobsimTimer mobsimTimer ,
79
- PassengerRequestCreator requestCreator , VrpOptimizer optimizer , Network network ,
80
- PassengerRequestValidator requestValidator , AdvanceRequestProvider advanceRequestProvider ) {
78
+ DefaultPassengerEngine (String mode , EventsManager eventsManager , MobsimTimer mobsimTimer , PassengerRequestCreator requestCreator ,
79
+ VrpOptimizer optimizer , Network network , PassengerRequestValidator requestValidator , AdvanceRequestProvider advanceRequestProvider ) {
81
80
this .mode = mode ;
82
81
this .mobsimTimer = mobsimTimer ;
83
82
this .requestCreator = requestCreator ;
@@ -106,17 +105,22 @@ public void doSimStep(double time) {
106
105
// event) after submission, but before departure, the PassengerEngine does not
107
106
// know this agent yet. Hence, we wait with setting the state to abort until the
108
107
// agent has arrived here (if ever).
109
-
108
+
110
109
Iterator <PassengerRequestRejectedEvent > iterator = rejectedRequestsEvents .iterator ();
111
-
110
+
112
111
while (iterator .hasNext ()) {
113
112
PassengerRequestRejectedEvent event = iterator .next ();
114
- MobsimPassengerAgent passenger = activePassengers .remove (event .getRequestId ());
113
+ if (event .getTime () == time ) {
114
+ // There is a potential race condition wrt processing rejection events between doSimStep() and handleEvent().
115
+ // To ensure a deterministic behaviour, we only process events from the previous time step.
116
+ break ;
117
+ }
115
118
119
+ MobsimPassengerAgent passenger = activePassengers .remove (event .getRequestId ());
116
120
if (passenger != null ) {
117
121
// not much else can be done for immediate requests
118
122
// set the passenger agent to abort - the event will be thrown by the QSim
119
- passenger .setStateToAbort (mobsimTimer . getTimeOfDay () );
123
+ passenger .setStateToAbort (time );
120
124
internalInterface .arrangeNextAgentState (passenger );
121
125
iterator .remove ();
122
126
}
@@ -137,20 +141,20 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> fromLinkI
137
141
internalInterface .registerAdditionalAgentOnLink (passenger );
138
142
139
143
Id <Link > toLinkId = passenger .getDestinationLinkId ();
140
-
144
+
141
145
// try to find a prebooked requests that is associated to this leg
142
- Leg leg = (Leg ) ((PlanAgent ) passenger ).getCurrentPlanElement ();
146
+ Leg leg = (Leg )((PlanAgent )passenger ).getCurrentPlanElement ();
143
147
PassengerRequest request = advanceRequestProvider .retrieveRequest (agent , leg );
144
-
148
+
145
149
if (request == null ) { // immediate request
146
150
Route route = ((Leg )((PlanAgent )passenger ).getCurrentPlanElement ()).getRoute ();
147
- request = requestCreator .createRequest (internalPassengerHandling .createRequestId (), passenger .getId (),
148
- route , getLink ( fromLinkId ), getLink (toLinkId ), now , now );
151
+ request = requestCreator .createRequest (internalPassengerHandling .createRequestId (), passenger .getId (), route , getLink ( fromLinkId ),
152
+ getLink (toLinkId ), now , now );
149
153
150
154
// must come before validateAndSubmitRequest (to come before rejection event)
151
155
eventsManager .processEvent (new PassengerWaitingEvent (now , mode , request .getId (), request .getPassengerId ()));
152
156
activePassengers .put (request .getId (), passenger );
153
-
157
+
154
158
validateAndSubmitRequest (passenger , request , now );
155
159
} else { // advance request
156
160
eventsManager .processEvent (new PassengerWaitingEvent (now , mode , request .getId (), request .getPassengerId ()));
@@ -162,7 +166,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> fromLinkI
162
166
pickupActivity .notifyPassengerIsReadyForDeparture (passenger , now );
163
167
}
164
168
}
165
-
169
+
166
170
return true ;
167
171
}
168
172
@@ -182,21 +186,20 @@ private void validateAndSubmitRequest(MobsimPassengerAgent passenger, PassengerR
182
186
183
187
private Link getLink (Id <Link > linkId ) {
184
188
return Preconditions .checkNotNull (network .getLinks ().get (linkId ),
185
- "Link id=%s does not exist in network for mode %s. Agent departs from a link that does not belong to that network?" ,
186
- linkId , mode );
189
+ "Link id=%s does not exist in network for mode %s. Agent departs from a link that does not belong to that network?" , linkId , mode );
187
190
}
188
191
189
192
/**
190
193
* There are two ways of interacting with the PassengerEngine:
191
- *
194
+ * <p>
192
195
* - (1) The stop activity tries to pick up a passenger and receives whether the
193
196
* pickup succeeded or not (see tryPickUpPassenger). In the classic
194
197
* implementation, the vehicle only calls tryPickUpPassenger at the time when it
195
198
* actually wants to pick up the person (at the end of the activity). It may
196
199
* happen that the person is not present yet. In that case, the pickup request
197
200
* is saved and notifyPassengerReady is called on the stop activity upen
198
201
* departure of the agent.
199
- *
202
+ * <p>
200
203
* - (2) If pickup and dropoff times are handled more flexibly by the stop
201
204
* activity, it might want to detect whether an agent is ready to be picked up,
202
205
* then start an "interaction time" and only after perform the actual pickup.
@@ -210,15 +213,13 @@ public boolean notifyWaitForPassenger(PassengerPickupActivity pickupActivity, Mo
210
213
waitingForPassenger .put (requestId , pickupActivity );
211
214
return false ;
212
215
}
213
-
216
+
214
217
return true ;
215
218
}
216
219
217
220
@ Override
218
- public boolean tryPickUpPassenger (PassengerPickupActivity pickupActivity , MobsimDriverAgent driver ,
219
- Id <Request > requestId , double now ) {
220
- return internalPassengerHandling .tryPickUpPassenger (driver , activePassengers .get (requestId ),
221
- requestId , now );
221
+ public boolean tryPickUpPassenger (PassengerPickupActivity pickupActivity , MobsimDriverAgent driver , Id <Request > requestId , double now ) {
222
+ return internalPassengerHandling .tryPickUpPassenger (driver , activePassengers .get (requestId ), requestId , now );
222
223
}
223
224
224
225
@ Override
@@ -243,10 +244,9 @@ public static Provider<PassengerEngine> createProvider(String mode) {
243
244
244
245
@ Override
245
246
public DefaultPassengerEngine get () {
246
- return new DefaultPassengerEngine (getMode (), eventsManager , mobsimTimer ,
247
- getModalInstance (PassengerRequestCreator .class ), getModalInstance (VrpOptimizer .class ),
248
- getModalInstance (Network .class ), getModalInstance (PassengerRequestValidator .class ),
249
- getModalInstance (AdvanceRequestProvider .class ));
247
+ return new DefaultPassengerEngine (getMode (), eventsManager , mobsimTimer , getModalInstance (PassengerRequestCreator .class ),
248
+ getModalInstance (VrpOptimizer .class ), getModalInstance (Network .class ), getModalInstance (PassengerRequestValidator .class ),
249
+ getModalInstance (AdvanceRequestProvider .class ));
250
250
}
251
251
};
252
252
}
0 commit comments