1 | package desmoj.core.simulator; |
2 | |
3 | import java.util.LinkedList; |
4 | import java.util.List; |
5 | import java.util.concurrent.LinkedBlockingQueue; |
6 | import java.util.concurrent.TimeUnit; |
7 | import java.util.concurrent.locks.ReentrantLock; |
8 | import desmoj.core.report.DebugNote; |
9 | |
10 | /** |
11 | * The scheduler is the main element controlling the run of a simulation. It |
12 | * controls the event-list in which all scheduled events are stored, picks the |
13 | * next event to be processed and advances the simulation clock accordingly. |
14 | * |
15 | * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011 |
16 | * @author Tim Lechler, modified by Ruth Meyer, Justin Neumann |
17 | * |
18 | * Licensed under the Apache License, Version 2.0 (the "License"); you |
19 | * may not use this file except in compliance with the License. You may |
20 | * obtain a copy of the License at |
21 | * http://www.apache.org/licenses/LICENSE-2.0 |
22 | * |
23 | * Unless required by applicable law or agreed to in writing, software |
24 | * distributed under the License is distributed on an "AS IS" BASIS, |
25 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
26 | * implied. See the License for the specific language governing |
27 | * permissions and limitations under the License. |
28 | * |
29 | */ |
30 | public class Scheduler extends NamedObject { |
31 | |
32 | /** |
33 | * The experiment this scheduler serves. |
34 | */ |
35 | protected Experiment myExperiment; |
36 | |
37 | /** |
38 | * The actual simulation clock for this scheduler. |
39 | */ |
40 | protected SimClock clock; |
41 | |
42 | /** |
43 | * The event-list used by the scheduler. |
44 | */ |
45 | protected EventList evList; |
46 | |
47 | /** |
48 | * Flag to indicate whether the current simulation is running or stopped. If |
49 | * true, the simulation is stopped, if false, the simulation is still |
50 | * running. This flag is especially polled by processes exiting any |
51 | * synchronized method used for passivating the process thus giving control |
52 | * back to the scheduler. |
53 | */ |
54 | protected boolean simulationFinished; |
55 | |
56 | /** |
57 | * Contains the event-note used by the current Schedulables. |
58 | */ |
59 | private EventNote _currentNote; |
60 | |
61 | /** |
62 | * Contains the current active Entity. |
63 | */ |
64 | private Entity _currentEntity1; |
65 | |
66 | /** |
67 | * Contains the current active Entity. |
68 | */ |
69 | private Entity _currentEntity2; |
70 | |
71 | /** |
72 | * Contains the current active Entity. |
73 | */ |
74 | private Entity _currentEntity3; |
75 | |
76 | /** |
77 | * Contains the current active SimProcess. |
78 | */ |
79 | private SimProcess _currentProcess; |
80 | |
81 | /** |
82 | * Contains the current active Event. |
83 | */ |
84 | private EventAbstract _currentEvent; |
85 | |
86 | /** |
87 | * Contains the current active model. |
88 | */ |
89 | private Model _currentModel; |
90 | |
91 | /** |
92 | * Contains the current active Schedulable. This is either the entity or |
93 | * simProcess if available, or the external event, if none of the first two |
94 | * are available. |
95 | */ |
96 | private Schedulable _currentSchedulable; |
97 | |
98 | /** |
99 | * Flag indicating if the event-list will process concurrent Events in |
100 | * random order or not. Default is not (<code>false</code>). (Modification |
101 | * by Ruth Meyer, 11/2001) |
102 | */ |
103 | private boolean _randomizingConcurrentEvents = false; |
104 | |
105 | /** |
106 | * The execution speed rate. Default is zero (as-fast-as-possible). |
107 | * (Modification by Felix Klueckmann, 05/2009) |
108 | */ |
109 | private double _executionSpeedRate = 0.0; |
110 | |
111 | /** |
112 | * The point in physical time (real time) of the last change of the |
113 | * execution speed rate (in nanoseconds). (Modification by Felix Klueckmann, |
114 | * 05/2009) |
115 | */ |
116 | private long _realTimeAtResetInNanos; |
117 | |
118 | /** |
119 | * The point in simulation time of the last change of the execution speed |
120 | * rate or the last time the simulation was stopped . (Modification by Felix |
121 | * Klueckmann, 05/2009) |
122 | */ |
123 | private TimeInstant _simulationTimeAtReset; |
124 | |
125 | /** |
126 | * Flag indicating if the the execution speed rate was changed or the |
127 | * experiment was stopped since the last call of processNextEventNote(). |
128 | * (Modification by Felix Klueckmann, 05/2009) |
129 | */ |
130 | private boolean _timeReset; |
131 | |
132 | /** |
133 | * Lock for process synchronisation during a realtime execution. |
134 | * (Modification by Felix Klueckmann, 06/2009) |
135 | */ |
136 | private ReentrantLock _lock; |
137 | |
138 | /** |
139 | * The condition used for process synchronisation during a realtime |
140 | * execution. |
141 | */ |
142 | private java.util.concurrent.locks.Condition _waitSynchCondition; |
143 | |
144 | /** |
145 | * A threadsafte consumer/producer queue to store |
146 | * RealTimeEventWrapper-Objects send by external systems |
147 | */ |
148 | private java.util.concurrent.BlockingQueue<RealTimeEventWrapper> _realTimeEventQueue; |
149 | |
150 | /** |
151 | * Constructs a scheduler with given name and the event-list (i.e. inheritor |
152 | * of <code>desmoj.core.simulator.EventList</code>) to use. |
153 | * |
154 | * @param exp |
155 | * Experiment : The experiment that uses this Scheduler |
156 | * @param name |
157 | * java.lang.String : The scheduler's name |
158 | * @param eventList |
159 | * EventList : The event-list to store scheduled events |
160 | */ |
161 | |
162 | public Scheduler(Experiment exp, String name, EventList eventList) { |
163 | |
164 | super(name + "_scheduler"); // create a namedObject with given name |
165 | myExperiment = exp; |
166 | evList = eventList; |
167 | clock = new SimClock(name); // set reference to clock |
168 | simulationFinished = false; // set flag to "not yet finished", |
169 | _lock = new ReentrantLock(); |
170 | _waitSynchCondition = _lock.newCondition(); |
171 | _realTimeEventQueue = new LinkedBlockingQueue<RealTimeEventWrapper>(); |
172 | } |
173 | |
174 | /** |
175 | * Returns the actual simulation time as displayed by the simulation clock. |
176 | * |
177 | * @return TimeInstant : The current point in simulation time |
178 | */ |
179 | protected TimeInstant presentTime() { |
180 | |
181 | return clock.getTime(); |
182 | |
183 | } |
184 | |
185 | /** |
186 | * Returns the currently active Entity. Returns <code>null</code> if the current |
187 | * Schedulable happens to be an external event or a simprocess. |
188 | * Note that in case the current Event refers to more than one entity |
189 | * (<code>EventOfTwoEntities</code>, <code>EventOfThreeEntitties</code>), |
190 | * only the first entity is returned; to obtain all such entities, |
191 | * use <code>getAllCurrentEntities()</code> instead. |
192 | * |
193 | * @return Entity : The currently active Entity or |
194 | * <code>null</code> in case of an external event or a simprocess |
195 | * being the currently active Schedulable |
196 | */ |
197 | protected Entity getCurrentEntity() { |
198 | |
199 | return _currentEntity1; |
200 | |
201 | } |
202 | |
203 | /** |
204 | * Returns the currently active entities. Returns an empty list |
205 | * if the current Schedulable happens to be an external event or a sim-process. |
206 | * |
207 | * @return List<Entity> : A list containing the currently active entities |
208 | */ |
209 | protected List<Entity> getAllCurrentEntities() { |
210 | |
211 | List<Entity> entities = new LinkedList<Entity>(); |
212 | if (_currentEntity1 != null) entities.add(_currentEntity1); |
213 | if (_currentEntity2 != null) entities.add(_currentEntity2); |
214 | if (_currentEntity3 != null) entities.add(_currentEntity3); |
215 | |
216 | return entities; |
217 | |
218 | } |
219 | |
220 | |
221 | /** |
222 | * Returns the current active Event or <code>null</code>. Note that this |
223 | * method can also return an external event that can not be handled like an |
224 | * Event since it does not support scheduling together with an entity. |
225 | * Returns <code>null</code> if the current Schedulable happens to be a |
226 | * Sim-process that has been activated, thus no kind of Event is associated |
227 | * with it. |
228 | * |
229 | * @return Event : The currently active Event or external event or |
230 | * <code>null</code> if the current Schedulable happens to be an |
231 | * activated SimProcess |
232 | */ |
233 | protected EventAbstract getCurrentEvent() { |
234 | |
235 | return _currentEvent; |
236 | |
237 | } |
238 | |
239 | /** |
240 | * Returns the currently active model. |
241 | * |
242 | * @return Model : The currently active model or <code>null</code> in case |
243 | * of no model being connected so far. |
244 | */ |
245 | protected Model getCurrentModel() { |
246 | |
247 | return _currentModel; |
248 | |
249 | } |
250 | |
251 | /** |
252 | * Returns the currently active Schedulable object. This can be any of its |
253 | * subtypes Entity, SimProcess or external event in that order. |
254 | * For events referring to multiple enities, the first entity is returned. |
255 | * |
256 | * @return Schedulable : The currently active Schedulable |
257 | * @see Entity |
258 | * @see SimProcess |
259 | * @see ExternalEvent |
260 | */ |
261 | protected Schedulable getCurrentSchedulable() { |
262 | |
263 | return _currentSchedulable; |
264 | |
265 | } |
266 | |
267 | /** |
268 | * Returns the current SimProcess. Note that this method can only return a |
269 | * Sim-process. If the currently active Schedulable is not instance of |
270 | * Sim-process or an external event, <code>null</code> is returned. |
271 | * |
272 | * @return SimProcess : The currently active SimProcess or <code>null</code> |
273 | */ |
274 | protected SimProcess getCurrentSimProcess() { |
275 | |
276 | return _currentProcess; |
277 | |
278 | } |
279 | |
280 | /** |
281 | * Returns the current execution Speed Rate. |
282 | * |
283 | * @return double : The current execution speed rate. |
284 | */ |
285 | protected double getExecutionSpeedRate() { |
286 | return _executionSpeedRate; |
287 | } |
288 | |
289 | /** |
290 | * Returns the actual clock for this model. |
291 | * |
292 | * @return SimClock : The actual clock for simulation time |
293 | */ |
294 | protected SimClock getSimClock() { |
295 | |
296 | return clock; // not much else to do |
297 | |
298 | } |
299 | |
300 | /** |
301 | * Returns if the event-list processes concurrent Events in random order or |
302 | * not. |
303 | * |
304 | * @return boolean: <code>true</code> if concurrent Events are randomized, |
305 | * <code>false</code> otherwise |
306 | * @author Ruth Meyer |
307 | */ |
308 | public boolean isRandomizingConcurrentEvents() { |
309 | return this._randomizingConcurrentEvents; |
310 | } |
311 | |
312 | /** |
313 | * Preempts the currently running SimProcess. Method is called whenenver |
314 | * another Entity or SimProcess is scheduled with <code>TimeSpan.ZERO</code> |
315 | * or <code>presentTime()</code> as parameter for the simulation time. The |
316 | * current SimProcess is interrupted and will be scheduled to continue its |
317 | * lifecycle |
318 | * |
319 | * @param preemptNote |
320 | * EventNote - The event-note of the Schedulable preempting |
321 | * the current SimProcess |
322 | */ |
323 | void preemptSimProcess(EventNote preemptNote) { |
324 | |
325 | if (_currentProcess == null) { |
326 | myExperiment.sendWarning("Can't preempt current SimProcess! " |
327 | + "Command ignored.", "Scheduler : " + getName() |
328 | + " Method: preemptSimProcess(EventNote preemptNote)", |
329 | "The event-note reference passed as parameter is a null " |
330 | + "reference.", |
331 | "Always make sure to use valid references only."); |
332 | return; // preemption of currentprocess only |
333 | } |
334 | |
335 | preemptNote.setTime(presentTime()); |
336 | |
337 | EventNote currentNote = new EventNote(_currentProcess, null, |
338 | presentTime()); |
339 | |
340 | evList.insertAsFirst(currentNote); // schedule currentProcess.. |
341 | evList.insertAsFirst(preemptNote); |
342 | // ..to be next after preempting SimPr. |
343 | _currentProcess.passivate(); // and set current to sleep until then |
344 | |
345 | } |
346 | |
347 | /** |
348 | * Processes the next event-note on the event-list. Returns <code>true</code> |
349 | * if that EventNote has been processed correctly, <code>false</code> if an |
350 | * error occurred or the event-list is empty. |
351 | * |
352 | * @return boolean : Is <code>true</code> if the next event-note was |
353 | * processed correctly, <code>false</code> if not |
354 | */ |
355 | protected boolean processNextEventNote() { |
356 | // check if there still are Event notes to be processed |
357 | if (!(_executionSpeedRate > 0)) { |
358 | if (evList.isEmpty()) { |
359 | return false; // no more EventNote available -> exit |
360 | } |
361 | } else { |
362 | |
363 | while (true) { |
364 | this._lock.lock(); |
365 | if (evList.isEmpty() && _realTimeEventQueue.isEmpty()) { |
366 | // no Event waiting |
367 | _lock.unlock(); |
368 | return false; |
369 | } |
370 | if (myExperiment.isStopped()) { |
371 | // experiment has been stopped |
372 | _lock.unlock(); |
373 | return true; // there is an event |
374 | } |
375 | if (_timeReset) { |
376 | this._realTimeAtResetInNanos = System.nanoTime(); |
377 | this._simulationTimeAtReset = presentTime(); |
378 | this._timeReset = false; |
379 | } |
380 | |
381 | while (!_realTimeEventQueue.isEmpty()) { |
382 | // an event has been sent by an external system |
383 | |
384 | RealTimeEventWrapper currentRealTimeWrapper = _realTimeEventQueue |
385 | .poll();// get the next RealTimeEventWrapper and |
386 | // remove it from the queue |
387 | ExternalEvent currentRealTimeEvent = currentRealTimeWrapper |
388 | .getExternalEvent();// get the encapsulated |
389 | // ExternalEvent |
390 | |
391 | long weightedRealTimeEventNanos = (long) ((currentRealTimeWrapper |
392 | .getNanos() - _realTimeAtResetInNanos) * _executionSpeedRate); |
393 | |
394 | if (weightedRealTimeEventNanos < 0) { |
395 | // the ExternalEvent is in the future |
396 | myExperiment |
397 | .sendWarning( |
398 | "Can not schedule real time external event! " |
399 | + "The external event is discarded.", |
400 | "Scheduler of experiment " |
401 | + myExperiment.getName() |
402 | + " Method processNextEventNote() " |
403 | + "external event: " |
404 | + currentRealTimeEvent |
405 | .getName() |
406 | + " deviation in nanoseconds: " |
407 | + -weightedRealTimeEventNanos, |
408 | "The given real-time time stamp is in the future.", |
409 | "Real-time events are not supposed to be scheduled in the (real time) future."); |
410 | } else { |
411 | |
412 | TimeInstant realTimeNanosEquivalent = TimeOperations |
413 | .add(_simulationTimeAtReset, new TimeSpan( |
414 | weightedRealTimeEventNanos, |
415 | TimeUnit.NANOSECONDS)); |
416 | // calculate the simulation time equivalent to |
417 | // the real-time time stamp of the external event |
418 | |
419 | if (TimeInstant.isAfterOrEqual(realTimeNanosEquivalent, |
420 | presentTime())) { |
421 | // the event can be scheduled correctly |
422 | currentRealTimeEvent |
423 | .schedule(realTimeNanosEquivalent); |
424 | } else { |
425 | // the simulation time of the event is in the past |
426 | currentRealTimeEvent.schedule(presentTime()); |
427 | |
428 | myExperiment |
429 | .sendWarning( |
430 | "Can not schedule real time external event at the simulation time equivalent to the given timeStamp! " |
431 | + "The external event is scheduled at the present simulation time instead.", |
432 | "Scheduler of experiment " |
433 | + myExperiment.getName() |
434 | + " Method processNextEventNote() " |
435 | + "external event: " |
436 | + currentRealTimeEvent |
437 | .getName() |
438 | + " deviation in nanoseconds: " |
439 | + (presentTime() |
440 | .getTimeTruncated( |
441 | TimeUnit.NANOSECONDS) - weightedRealTimeEventNanos), |
442 | "The simulation time equivalent of the given time stamp is before the current simulation time. Can not perform a rollback.", |
443 | "Check if this deviation constitutes a problem."); |
444 | } |
445 | |
446 | } |
447 | |
448 | } |
449 | |
450 | // System.out.println("--------------------------"); |
451 | // if (!evList.isEmpty()) { |
452 | // EventNote note = evList.firstNote(); |
453 | // System.out.println(note.toString()); |
454 | // while (!(note == evList.lastNote())) { |
455 | // System.out.println(evList.nextNote(note)); |
456 | // note = evList.nextNote(note); |
457 | // } |
458 | // System.out.println("--------------------------"); |
459 | // } |
460 | // test code by felix |
461 | |
462 | _currentNote = evList.firstNote(); // get next event-note |
463 | long weightedTimeSinceReset = (long) ((System.nanoTime() - _realTimeAtResetInNanos) * _executionSpeedRate); |
464 | // calculate the real time passed since the last time reset |
465 | // considering the execution speed rate |
466 | |
467 | long timeToWait = (long) ((TimeOperations.diff( |
468 | _currentNote.getTime(), _simulationTimeAtReset) |
469 | .getTimeTruncated(TimeUnit.NANOSECONDS) - weightedTimeSinceReset) / _executionSpeedRate); |
470 | // calculate the time the thread has to wait |
471 | if (timeToWait > 0) { |
472 | // there is a need to wait |
473 | try { |
474 | _waitSynchCondition.awaitNanos(timeToWait); |
475 | |
476 | } catch (InterruptedException e) { |
477 | e.printStackTrace(); |
478 | } finally { |
479 | this._lock.unlock(); |
480 | } |
481 | } else { |
482 | this._lock.unlock(); |
483 | } |
484 | if (!_timeReset && _realTimeEventQueue.isEmpty()) { |
485 | break; |
486 | } |
487 | |
488 | } |
489 | } |
490 | _currentNote = evList.firstNote(); // get next event-note |
491 | TimeInstant nextTime = _currentNote.getTime(); |
492 | // check if the next event-note is in the future |
493 | if (TimeInstant.isAfter(nextTime, presentTime())) { |
494 | this.advanceTime(presentTime(), nextTime); |
495 | } else { |
496 | // throw an exception if the next event-note is in the past |
497 | if (TimeInstant.isBefore(nextTime, presentTime())) { |
498 | throw (new desmoj.core.exception.SimAbortedException( |
499 | new desmoj.core.report.ErrorMessage( |
500 | null, |
501 | "The simulation Time of the next event is in the past! Simulation aborted.", |
502 | "Class : Scheduler Method : processNextEventNote()", |
503 | "the simulation time of the next event-note (" |
504 | + _currentNote |
505 | + ") is before the current simulation time : " |
506 | + presentTime(), |
507 | "Make sure not to schedule events in the past.", |
508 | null))); |
509 | } |
510 | } |
511 | // update the clock and its observers |
512 | |
513 | // changes to event-list and 'current' variables can only be made after |
514 | // every |
515 | // Observer registered with the clock has made their updates |
516 | |
517 | // take EventNote from EventList |
518 | evList.remove(_currentNote); |
519 | |
520 | // set 'current' variables |
521 | // determine Entity and SimProcess, if applicable |
522 | _currentEntity1 = _currentNote.getEntity1(); // multiple entities |
523 | _currentEntity2 = _currentNote.getEntity2(); |
524 | _currentEntity3 = _currentNote.getEntity3(); |
525 | |
526 | _currentProcess = null; |
527 | _currentSchedulable = null; |
528 | |
529 | if (_currentEntity1 != null) |
530 | { |
531 | _currentModel = _currentEntity1.getModel(); |
532 | _currentSchedulable = _currentEntity1; |
533 | _currentEntity1.removeEventNote(_currentNote); |
534 | if (_currentEntity1 instanceof SimProcess) { // a real SimProcess |
535 | _currentProcess = (SimProcess) _currentEntity1; |
536 | } |
537 | } |
538 | if (_currentEntity2 != null) |
539 | { |
540 | _currentEntity2.removeEventNote(_currentNote); |
541 | } |
542 | if (_currentEntity3 != null) |
543 | { |
544 | _currentEntity3.removeEventNote(_currentNote); |
545 | } |
546 | |
547 | // determine Event resp. external event |
548 | _currentEvent = _currentNote.getEvent(); |
549 | |
550 | if (_currentEvent != null && _currentProcess == null) { |
551 | |
552 | _currentEvent.removeEventNote(_currentNote); |
553 | |
554 | if (_currentSchedulable == null) { |
555 | |
556 | _currentSchedulable = _currentEvent; |
557 | _currentModel = _currentEvent.getModel(); |
558 | } |
559 | } |
560 | |
561 | // just check if everything is still allright |
562 | // currSched. must have been set to something other than null by now |
563 | // otherwise : throw (new desmoj.exception.DESMOJException()); |
564 | if (_currentSchedulable == null) |
565 | return false; |
566 | |
567 | // clear time value and discard EventNote |
568 | _currentNote.setTime(null); |
569 | _currentNote = null; |
570 | |
571 | // determine if event-oriented or process-oriented |
572 | if (_currentEvent != null) { // event-oriented |
573 | |
574 | if (_currentEvent.getNumberOfEntities()==1) // Event for one entity |
575 | { |
576 | ((Event<Entity>) _currentEvent).eventRoutine(_currentEntity1); |
577 | } |
578 | |
579 | else if (_currentEvent.getNumberOfEntities()==2)// Event for two entities |
580 | { |
581 | ((EventOf2Entities<Entity, Entity>) _currentEvent).eventRoutine(_currentEntity1, _currentEntity2); |
582 | } |
583 | |
584 | else if (_currentEvent.getNumberOfEntities()==3)// Event for three entities |
585 | { |
586 | ((EventOf3Entities<Entity, Entity, Entity>) _currentEvent).eventRoutine(_currentEntity1, _currentEntity2, _currentEntity3); |
587 | } |
588 | |
589 | else //external event! |
590 | { |
591 | ((ExternalEvent) _currentEvent).eventRoutine(); |
592 | } |
593 | |
594 | // this is where it all happens |
595 | } else { // process-oriented |
596 | |
597 | // The current SimProcess to hand control over to may have terminated |
598 | // already |
599 | // so the scheduler must not start it |
600 | if (!_currentProcess.isTerminated()) { |
601 | |
602 | // The current SimProcess can either be running, thus waiting in a |
603 | // block |
604 | // or still not have been started |
605 | if (_currentProcess.isReady()) { |
606 | // currentProcess is already running |
607 | |
608 | // main thread passes control over to currentProcess' |
609 | // SimThread |
610 | // executing the sim-process' lifeCycle method until |
611 | // hold / passivate |
612 | // or end of lifeCycle |
613 | _currentProcess.resume(); |
614 | |
615 | } else { // currentProcess is starting for the first time |
616 | |
617 | _currentProcess.start(); // start him up |
618 | |
619 | } |
620 | |
621 | // when hold / passivate or end of lifeCycle are passed, the |
622 | // control |
623 | // is handed back to the main thread here and there's nothing |
624 | // else to do |
625 | // but return true to state that this event-note has been |
626 | // processed correctly |
627 | |
628 | } else { |
629 | // this must not happen, but we check on it anyway |
630 | myExperiment |
631 | .sendWarning("Can not activate scheduled SimProcess! " |
632 | + "Command ignored.", |
633 | "Scheduler of experiment " |
634 | + myExperiment.getName() |
635 | + " Method processNextEventNote() " |
636 | + "SimProcess : " |
637 | + _currentProcess.getName(), |
638 | "The sim-process to be activated to take over control has " |
639 | + "already terminated.", |
640 | "Internal DESMOJ-Error. Please report to DESMOJ-Support."); |
641 | } |
642 | |
643 | } |
644 | if (_executionSpeedRate > 0) { |
645 | // calculate deviation |
646 | long simTimeSinceReset = TimeOperations.diff(presentTime(), |
647 | _simulationTimeAtReset).getTimeTruncated( |
648 | TimeUnit.NANOSECONDS); |
649 | long realTimeSinceReset = (System.nanoTime() - _realTimeAtResetInNanos); |
650 | long deviationInNanoseconds = (long) (realTimeSinceReset - (simTimeSinceReset / _executionSpeedRate)); |
651 | // System.out.println("SimTimeSinceReset: " + simTimeSinceReset |
652 | // + ", RealTimeSinceReset: " + realTimeSinceReset |
653 | // + ", Weighted deviation: " + deviationInNanoseconds); |
654 | |
655 | if (_currentEvent != null) { |
656 | // event-oriented |
657 | |
658 | long deadLine = _currentEvent.getRealTimeConstraint(); |
659 | // the deadLine of this event |
660 | |
661 | if (deadLine > 0 && deadLine < deviationInNanoseconds) { |
662 | // the real-time deadline was missed |
663 | myExperiment.sendWarning( |
664 | "The real-time deadline of this event was missed!", |
665 | "Scheduler of experiment " + myExperiment.getName() |
666 | + " Method processNextEventNote() " |
667 | + "Event : " + _currentEvent.getName(), |
668 | "The real-time deadline of this event was " |
669 | + deadLine + " nanoseconds. It was missed by " |
670 | + (deviationInNanoseconds - deadLine) |
671 | + " nanoseconds.", |
672 | "Check if the deadline can be met."); |
673 | } |
674 | } else { |
675 | // process-oriented |
676 | |
677 | long deadLine = _currentProcess.getRealTimeConstraint(); |
678 | // the deadLine of this SimProcess |
679 | |
680 | if (deadLine > 0 && deadLine < deviationInNanoseconds) { |
681 | // the real-time deadline was missed |
682 | myExperiment |
683 | .sendWarning( |
684 | "The real-time deadline of this SimProcess was missed!", |
685 | "Scheduler of experiment " |
686 | + myExperiment.getName() |
687 | + " Method processNextEventNote() " |
688 | + "SimProcess : " |
689 | + _currentProcess.getName(), |
690 | "The real-time deadline of this SimProcess was " |
691 | + deadLine |
692 | + " nanoseconds. It was missed by " |
693 | + (deviationInNanoseconds - deadLine) |
694 | + " nanoseconds.", |
695 | "Check if the deadline can be met."); |
696 | } |
697 | } |
698 | |
699 | } |
700 | |
701 | return true; // everything processed alright |
702 | |
703 | } |
704 | |
705 | /** |
706 | * This method is called to notify simulator about the time |
707 | * passed between the execution of two events with a positive |
708 | * (non-zero) offset. The implementation of this method just |
709 | * sets the scheduler's clock to the new instant; note, though, |
710 | * that extensions to DESMO-J may overwrite this method |
711 | * to conduct more complex operations, e.g. extrapolate |
712 | * variables in continuous simulation. |
713 | * |
714 | * @param now |
715 | * TimeInstant : The current point in simulation time |
716 | * @param next |
717 | * TimeInstant : The next point in simulation time to |
718 | * advance the clock to (e.g. instant of the next event) |
719 | */ |
720 | protected void advanceTime(TimeInstant now, TimeInstant next) { |
721 | |
722 | // just update the simulation clock to the instant of |
723 | // the next event |
724 | clock.setTime(next); |
725 | } |
726 | |
727 | |
728 | /** |
729 | * Schedules the external event to happen at the simulation time equivalent |
730 | * to the current value of wall-clock time. |
731 | * |
732 | * @param what |
733 | * ExternalEvent : The external event to be scheduled |
734 | * |
735 | */ |
736 | protected void realTimeSchedule(RealTimeEventWrapper what) { |
737 | if (!myExperiment.isRunning()) { |
738 | myExperiment |
739 | .sendWarning( |
740 | "Can not schedule real time external event! Command ignored.", |
741 | "Experiment '" |
742 | + getName() |
743 | + "' method void realTimeSchedule(ExternalEvent what).", |
744 | "The experiment is not running.", |
745 | "events can only be scheduled when the exeriment is running."); |
746 | return; |
747 | } |
748 | if (what == null) { // check for null reference |
749 | myExperiment.sendWarning("Can't schedule ExternalEvent! " |
750 | + "Command ignored.", "Scheduler : " + getName() |
751 | + " Method: realTimeSchedule(ExternalEvent what)", |
752 | "The ExternalEvent reference passed is a " |
753 | + "null references.", |
754 | "Always make sure to use valid references only."); |
755 | return; |
756 | } |
757 | |
758 | try { |
759 | // put the given Event wrapper into the thread-safe Event queue |
760 | _realTimeEventQueue.put(what); |
761 | } catch (InterruptedException e) { |
762 | myExperiment.sendWarning("Can't schedule external event! " |
763 | + "Command ignored.", "Scheduler : " + getName() |
764 | + " Method: realTimeSchedule(ExternalEvent who)", |
765 | "The Thread waiting to schedule the given external event " |
766 | + "was interrupted.", |
767 | "A Thread has to wait until space becomes available"); |
768 | |
769 | } |
770 | _lock.lock(); |
771 | _waitSynchCondition.signal();// signal that a new real time Event is |
772 | // available |
773 | _lock.unlock(); |
774 | } |
775 | |
776 | /** |
777 | * Schedules the event to happen after a specified time. Checks that only |
778 | * legal combinations of valid parameters are scheduled. |
779 | * <p> |
780 | * <DIV align=center> |
781 | * <TABLE BORDER > |
782 | * <CAPTION>Valid scheduling types </CAPTION> |
783 | * <TR> |
784 | * <TH><DIV align=center>scheduling type</TH> |
785 | * <TH>Entity object</TH> |
786 | * <TH>Event object</TH> |
787 | * </TR> |
788 | * <TR> |
789 | * <TH>Event oriented</TH> |
790 | * <TD>Event or SimProcess</TD> |
791 | * <TD>Event</TD> |
792 | * </TR> |
793 | * <TR> |
794 | * <TH>process oriented</TH> |
795 | * <TD>SimProcess</TD> |
796 | * <TD>null</TD> |
797 | * </TR> |
798 | * <TR> |
799 | * <TH>external event</TH> |
800 | * <TD>null</TD> |
801 | * <TD>external event</TD> |
802 | * </TR> |
803 | * </TABLE> |
804 | * </DIV> |
805 | * |
806 | * @param who |
807 | * Entity : The Entity to be scheduled |
808 | * @param dt |
809 | * TimeSpan : The point in simulation time for the event to happen |
810 | * as an offset to the current simulation time |
811 | */ |
812 | protected void reSchedule(Schedulable who, TimeSpan dt) { |
813 | |
814 | if (dt == null) { |
815 | myExperiment |
816 | .sendWarning( |
817 | "Can't reschedule Schedulable at given time! " |
818 | + "Command ignored.", |
819 | "Scheduler : " |
820 | + getName() |
821 | + " Method: reSchedule(Schedulable who, TimeSpan dt)", |
822 | "The simulation time reference passed as parameter is a " |
823 | + "null reference.", |
824 | "Always make sure to use valid references only."); |
825 | return; // time missing |
826 | } |
827 | |
828 | if (who == null) { |
829 | myExperiment |
830 | .sendWarning( |
831 | "Can't reschedule Schedulable at given time! " |
832 | + "Command ignored.", |
833 | "Scheduler : " |
834 | + getName() |
835 | + " Method: reSchedule(Schedulable who, TimeSpan dt)", |
836 | "The Schedulable reference passed as parameter is a " |
837 | + "null reference.", |
838 | "Always make sure to use valid references only."); |
839 | return; // Schedulable missing |
840 | } |
841 | |
842 | if (!who.isScheduled()) { |
843 | myExperiment |
844 | .sendWarning( |
845 | "Can't reschedule Schedulable at given time! " |
846 | + "Command ignored.", |
847 | "Scheduler : " |
848 | + getName() |
849 | + " Method: reSchedule(Schedulable who, TimeSpan dt)", |
850 | "The Schedulable given is not scheduled, thus can not be " |
851 | + "rescheduled.", |
852 | "To reschedule a Schedulable, it must already be scheduled. " |
853 | + "You can check that by calling the Schedulable's " |
854 | + "isScheduled() method"); |
855 | return; |
856 | // I can't be rescheduled, I haven't even been scheduled yet |
857 | } |
858 | |
859 | // all parameters checked, now remove the Schedulable's EventNote |
860 | // first... |
861 | List<EventNote> notes = who.getEventNotes(); |
862 | for (EventNote note : notes) { |
863 | evList.remove(note); |
864 | note.setTime(TimeOperations.add(presentTime(), dt)); |
865 | |
866 | if (dt == TimeSpan.ZERO) { // preempting schedule for processes |
867 | |
868 | if (_currentProcess == null) { // currently Event -> no preemption |
869 | // inserted as first in the event-list with the current time as |
870 | // activation |
871 | evList.insertAsFirst(note); |
872 | |
873 | } else { // currently SimProcess -> preempt! |
874 | |
875 | preemptSimProcess(note); |
876 | } |
877 | |
878 | } else { |
879 | |
880 | // all parameters checked, now reinsert note |
881 | evList.insert(note); |
882 | |
883 | } |
884 | } |
885 | } |
886 | |
887 | /** |
888 | * Schedules the event to happen at the specified time. Checks that only |
889 | * legal combinations of valid parameters are scheduled. |
890 | * <p> |
891 | * <DIV align=center> |
892 | * <TABLE BORDER > |
893 | * <CAPTION>Valid scheduling types </CAPTION> |
894 | * <TR> |
895 | * <TH><DIV align=center>scheduling type</TH> |
896 | * <TH>Entity object</TH> |
897 | * <TH>Event object</TH> |
898 | * </TR> |
899 | * <TR> |
900 | * <TH>Event oriented</TH> |
901 | * <TD>Event or SimProcess</TD> |
902 | * <TD>Event</TD> |
903 | * </TR> |
904 | * <TR> |
905 | * <TH>process oriented</TH> |
906 | * <TD>SimProcess</TD> |
907 | * <TD>null</TD> |
908 | * </TR> |
909 | * <TR> |
910 | * <TH>external event</TH> |
911 | * <TD>null</TD> |
912 | * <TD>external event</TD> |
913 | * </TR> |
914 | * </TABLE> |
915 | * </DIV> |
916 | * |
917 | * @param who |
918 | * Entity : The Entity to be scheduled |
919 | * @param time |
920 | * TimeInstant : The point in simulation time for the event to happen |
921 | */ |
922 | protected void reSchedule(Schedulable who, TimeInstant time) { |
923 | |
924 | if (time == null) { |
925 | myExperiment |
926 | .sendWarning( |
927 | "Can't reschedule Schedulable at given time! " |
928 | + "Command ignored.", |
929 | "Scheduler : " |
930 | + getName() |
931 | + " Method: reSchedule(Schedulable who, TimeInstant time)", |
932 | "The simulation time reference passed as parameter is a " |
933 | + "null reference.", |
934 | "Always make sure to use valid references only."); |
935 | return; // time missing |
936 | } |
937 | |
938 | if (who == null) { |
939 | myExperiment |
940 | .sendWarning( |
941 | "Can't reschedule Schedulable at given time! " |
942 | + "Command ignored.", |
943 | "Scheduler : " |
944 | + getName() |
945 | + " Method: reSchedule(Schedulable who, TimeInstant time)", |
946 | "The Schedulable reference passed as parameter is a " |
947 | + "null reference.", |
948 | "Always make sure to use valid references only."); |
949 | return; // Schedulable missing |
950 | } |
951 | |
952 | if (!who.isScheduled()) { |
953 | myExperiment |
954 | .sendWarning( |
955 | "Can't reschedule Schedulable at given time! " |
956 | + "Command ignored.", |
957 | "Scheduler : " |
958 | + getName() |
959 | + " Method: reSchedule(Schedulable who, TimeInstant time)", |
960 | "The Schedulable given is not scheduled, thus can not be " |
961 | + "rescheduled.", |
962 | "To reschedule a Schedulable, it must already be scheduled. " |
963 | + "You can check that by calling the Schedulable's " |
964 | + "isScheduled() method"); |
965 | return; |
966 | // I can't be rescheduled, I haven't even been scheduled yet |
967 | } |
968 | |
969 | if (TimeInstant.isBefore(time, this.presentTime())) { |
970 | myExperiment |
971 | .sendWarning( |
972 | "Can't reschedule Schedulable at given time! " |
973 | + "Command ignored.", |
974 | "Scheduler : " |
975 | + getName() |
976 | + " Method: reSchedule(Schedulable who, TimeInstant time)", |
977 | "The instant given is in the past.", |
978 | "To reschedule a Schedulable, use a TimeInstant no earlier than the present time. " |
979 | + "The present time can be obtained using the " |
980 | + "presentTime() method"); |
981 | return; |
982 | // I can't be rescheduled, TimeInstant has already passed. |
983 | } |
984 | |
985 | // all parameters checked, now remove the Schedulable's EventNote |
986 | // first... |
987 | EventNote note = who.getEventNotes().get(0); |
988 | evList.remove(note); |
989 | note.setTime(time); |
990 | |
991 | if (this.presentTime() == time) { // preempting schedule for processes |
992 | |
993 | if (_currentProcess == null) { // currently Event -> no preemption |
994 | // inserted as first in the event-list with the current time as |
995 | // activation |
996 | evList.insertAsFirst(note); |
997 | return; |
998 | |
999 | } else { // currently SimProcess -> preempt! |
1000 | |
1001 | preemptSimProcess(note); |
1002 | return; |
1003 | |
1004 | } |
1005 | |
1006 | } |
1007 | |
1008 | // all parameters checked, now reinsert note |
1009 | evList.insert(note); |
1010 | |
1011 | } |
1012 | |
1013 | /** |
1014 | * Schedules the event to happen after a specified time span. Checks that only |
1015 | * legal combinations of valid parameters are scheduled. |
1016 | * <p> |
1017 | * <DIV align=center> |
1018 | * <TABLE BORDER > |
1019 | * <CAPTION>Valid scheduling types </CAPTION> |
1020 | * <TR> |
1021 | * <TH><DIV align=center>scheduling type</TH> |
1022 | * <TH>Entity object</TH> |
1023 | * <TH>Event object</TH> |
1024 | * </TR> |
1025 | * <TR> |
1026 | * <TH>Event oriented</TH> |
1027 | * <TD>Event or SimProcess</TD> |
1028 | * <TD>Event</TD> |
1029 | * </TR> |
1030 | * <TR> |
1031 | * <TH>process oriented</TH> |
1032 | * <TD>SimProcess</TD> |
1033 | * <TD>null</TD> |
1034 | * </TR> |
1035 | * <TR> |
1036 | * <TH>external event</TH> |
1037 | * <TD>null</TD> |
1038 | * <TD>external event</TD> |
1039 | * </TR> |
1040 | * </TABLE> |
1041 | * </DIV> |
1042 | * |
1043 | * @param who |
1044 | * Entity : The Entity to be scheduled |
1045 | * @param what |
1046 | * Event : The event to manipulate the entity |
1047 | * @param dt |
1048 | * TimeSpan : The point in simulation time for the event to happen |
1049 | * as an offset to the current simulation time |
1050 | */ |
1051 | protected void schedule(Entity who, EventAbstract what, TimeSpan dt) |
1052 | { |
1053 | |
1054 | if (dt == null) { |
1055 | myExperiment.sendWarning( |
1056 | "Can't schedule Entity and Event at given " |
1057 | + "time! Command ignored.", "Scheduler : " |
1058 | + getName() + " Method: schedule(Entity who, " |
1059 | + "EventAbstract what, TimeSpan dt)", |
1060 | "The simulation time reference passed as parameter is a " |
1061 | + "null reference.", |
1062 | "Always make sure to use valid references only."); |
1063 | return; // time missing |
1064 | } |
1065 | |
1066 | if ((who == null) && (what == null)) { |
1067 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1068 | + "Command ignored.", "Scheduler : " + getName() |
1069 | + " Method: schedule(Entity who, " |
1070 | + "EventAbstract what, TimeSpan dt)", |
1071 | "The Event and Entity references passed are both " |
1072 | + "null references.", |
1073 | "Either Event or Entity references must be valid."); |
1074 | return; // no real parameters here anyway |
1075 | } |
1076 | |
1077 | if ((who == null) && !(what instanceof ExternalEvent)) { |
1078 | myExperiment.sendWarning("Can't schedule Event! Command ignored.", |
1079 | "Scheduler : " + getName() |
1080 | + " Method: schedule(Entity who, " |
1081 | + "EventAbstract what, TimeSpan dt)", |
1082 | "The Entity reference passed is a null reference but the " |
1083 | + "Event references is not an external event.", |
1084 | "If no valid Entity is given, the event must be of type " |
1085 | + "external event."); |
1086 | return; // if no Entity it must be ExternalEvent |
1087 | } |
1088 | |
1089 | if (!(who instanceof SimProcess) && (what == null)) { |
1090 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1091 | + "Command ignored.", "Scheduler : " + getName() |
1092 | + " Method: schedule(Entity who, " |
1093 | + "EventAbstract what, TimeSpan dt)", |
1094 | "The Entity needs a valid Event to be scheduled with.", |
1095 | "Only SimProcesses may be scheduled without events."); |
1096 | return; // Event needed with Entity |
1097 | } |
1098 | |
1099 | if(what != null) |
1100 | { |
1101 | if (what.getNumberOfEntities() > 1) |
1102 | { |
1103 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1104 | + "Command ignored.", "Scheduler : " + getName() |
1105 | + " Method: schedule(Entity who, " |
1106 | + "EventAbstract what, TimeSpan dt)", |
1107 | "The method needs the correct Event to be scheduled with.", |
1108 | "You are using an event for multiple entities. You need an event for a single entity."); |
1109 | return; // Event with only one entity needed |
1110 | } |
1111 | } |
1112 | |
1113 | TimeInstant time = TimeOperations.add(presentTime(), dt); |
1114 | // set time for being scheduled |
1115 | |
1116 | EventNote note = new EventNote(who, what, time); |
1117 | |
1118 | if (dt == TimeSpan.ZERO) { // preempting schedule for processes |
1119 | if (_currentProcess == null) { // currently Event -> no preemption |
1120 | // inserted as first in the event-list with the current time as |
1121 | // activation |
1122 | evList.insertAsFirst(note); |
1123 | return; |
1124 | } else { // currently SimProcess -> preempt! |
1125 | preemptSimProcess(note); |
1126 | return; |
1127 | } |
1128 | } |
1129 | |
1130 | // all parameters checked, now schedule Event |
1131 | evList.insert(note); |
1132 | |
1133 | } |
1134 | |
1135 | /** |
1136 | * Schedules the event to happen after a specified time span. Checks that only |
1137 | * legal combinations of valid parameters are scheduled. |
1138 | * <p> |
1139 | * <DIV align=center> |
1140 | * <TABLE BORDER > |
1141 | * <CAPTION>Valid scheduling types </CAPTION> |
1142 | * <TR> |
1143 | * <TH><DIV align=center>scheduling type</TH> |
1144 | * <TH>Entity object</TH> |
1145 | * <TH>Event object</TH> |
1146 | * </TR> |
1147 | * <TR> |
1148 | * <TH>Event oriented</TH> |
1149 | * <TD>Event or SimProcess</TD> |
1150 | * <TD>Event</TD> |
1151 | * </TR> |
1152 | * <TR> |
1153 | * <TH>process oriented</TH> |
1154 | * <TD>SimProcess</TD> |
1155 | * <TD>null</TD> |
1156 | * </TR> |
1157 | * <TR> |
1158 | * <TH>external event</TH> |
1159 | * <TD>null</TD> |
1160 | * <TD>external event</TD> |
1161 | * </TR> |
1162 | * </TABLE> |
1163 | * </DIV> |
1164 | * |
1165 | * @param who1 |
1166 | * Entity : The first entity to be scheduled |
1167 | * |
1168 | * @param who2 |
1169 | * Entity : The second entity to be scheduled |
1170 | * |
1171 | * @param what |
1172 | * EventOf2Entities : The event to manipulate the two entities |
1173 | * @param dt |
1174 | * TimeSpan : The point in simulation time for the event to happen |
1175 | * as an offset to the current simulation time |
1176 | */ |
1177 | protected void schedule(Entity who1, Entity who2, EventOf2Entities<?, ?> what, TimeSpan dt) { |
1178 | |
1179 | if (dt == null) { |
1180 | myExperiment.sendWarning( |
1181 | "Can't schedule Entity and Event at given " |
1182 | + "time! Command ignored.", "Scheduler : " |
1183 | + getName() + " Method: schedule(Entity who1, Entity who2, " |
1184 | + "EventOf2Entities what, TimeSpan dt)", |
1185 | "The simulation time reference passed as parameter is a " |
1186 | + "null reference.", |
1187 | "Always make sure to use valid references only."); |
1188 | return; // time missing |
1189 | } |
1190 | |
1191 | if ((who1 == null) && (what == null)) { |
1192 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1193 | + "Command ignored.", "Scheduler : " + getName() |
1194 | + " Method: schedule(Entity who1, Entity who2, " |
1195 | + "EventOf2Entities what, TimeSpan dt)", |
1196 | "The event and first entity references passed are both " |
1197 | + "null references.", |
1198 | "Either Event or first entity references must be valid."); |
1199 | return; // no real parameters here anyway |
1200 | } |
1201 | |
1202 | if ((who2 == null) && (what == null)) { |
1203 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1204 | + "Command ignored.", "Scheduler : " + getName() |
1205 | + " Method: schedule(Entity who1, Entity who2, " |
1206 | + "EventOf2Entities what, TimeSpan dt)", |
1207 | "The event and second entity references passed are both " |
1208 | + "null references.", |
1209 | "Either Event or second entity references must be valid."); |
1210 | return; // no real parameters here anyway |
1211 | } |
1212 | |
1213 | if (!(who1 instanceof SimProcess) && (what == null)) { |
1214 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1215 | + "Command ignored.", "Scheduler : " + getName() |
1216 | + " Method: schedule(Entity who1, Entity who2, " |
1217 | + "EventOf2Entities what, TimeSpan dt)", |
1218 | "The first entity needs a valid Event to be scheduled with.", |
1219 | "Only SimProcesses may be scheduled without events."); |
1220 | return; // Event needed with Entity |
1221 | } |
1222 | |
1223 | if (!(who2 instanceof SimProcess) && (what == null)) { |
1224 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1225 | + "Command ignored.", "Scheduler : " + getName() |
1226 | + " Method: schedule(Entity who1, Entity who2, " |
1227 | + "EventOf2Entities what, TimeSpan dt)", |
1228 | "The second entity needs a valid Event to be scheduled with.", |
1229 | "Only SimProcesses may be scheduled without events."); |
1230 | return; // Event needed with Entity |
1231 | } |
1232 | |
1233 | TimeInstant time = TimeOperations.add(presentTime(), dt); |
1234 | // set time for being scheduled |
1235 | |
1236 | EventNote note = new EventNote(who1, who2, what, time); |
1237 | |
1238 | if (dt == TimeSpan.ZERO) { // preempting schedule for processes |
1239 | if (_currentProcess == null) { // currently Event -> no preemption |
1240 | // inserted as first in the event-list with the current time as |
1241 | // activation |
1242 | evList.insertAsFirst(note); |
1243 | return; |
1244 | } else { // currently SimProcess -> preempt! |
1245 | preemptSimProcess(note); |
1246 | return; |
1247 | } |
1248 | } |
1249 | |
1250 | // all parameters checked, now schedule Event |
1251 | evList.insert(note); |
1252 | |
1253 | } |
1254 | |
1255 | /** |
1256 | * Schedules the event to happen after a specified time span. Checks that only |
1257 | * legal combinations of valid parameters are scheduled. |
1258 | * <p> |
1259 | * <DIV align=center> |
1260 | * <TABLE BORDER > |
1261 | * <CAPTION>Valid scheduling types </CAPTION> |
1262 | * <TR> |
1263 | * <TH><DIV align=center>scheduling type</TH> |
1264 | * <TH>Entity object</TH> |
1265 | * <TH>Event object</TH> |
1266 | * </TR> |
1267 | * <TR> |
1268 | * <TH>Event oriented</TH> |
1269 | * <TD>Event or SimProcess</TD> |
1270 | * <TD>Event</TD> |
1271 | * </TR> |
1272 | * <TR> |
1273 | * <TH>process oriented</TH> |
1274 | * <TD>SimProcess</TD> |
1275 | * <TD>null</TD> |
1276 | * </TR> |
1277 | * <TR> |
1278 | * <TH>external event</TH> |
1279 | * <TD>null</TD> |
1280 | * <TD>external event</TD> |
1281 | * </TR> |
1282 | * </TABLE> |
1283 | * </DIV> |
1284 | * |
1285 | * @param who1 |
1286 | * Entity : The first entity to be scheduled |
1287 | * |
1288 | * @param who2 |
1289 | * Entity : The second entity to be scheduled |
1290 | * |
1291 | * @param who3 |
1292 | * Entity : The third entity to be scheduled |
1293 | * |
1294 | * @param what |
1295 | * EventOf3Entities : The event to manipulate the two entities |
1296 | * @param dt |
1297 | * TimeSpan : The point in simulation time for the event to happen |
1298 | * as an offset to the current simulation time |
1299 | */ |
1300 | protected void schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what, TimeSpan dt) { |
1301 | |
1302 | if (dt == null) { |
1303 | myExperiment.sendWarning( |
1304 | "Can't schedule Entity and Event at given " |
1305 | + "time! Command ignored.", "Scheduler : " |
1306 | + getName() + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1307 | + "EventOf3Entities what, TimeSpan dt)", |
1308 | "The simulation time reference passed as parameter is a " |
1309 | + "null reference.", |
1310 | "Always make sure to use valid references only."); |
1311 | return; // time missing |
1312 | } |
1313 | |
1314 | if ((who1 == null) && (what == null)) { |
1315 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1316 | + "Command ignored.", "Scheduler : " + getName() |
1317 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1318 | + "EventOf3Entities what, TimeSpan dt)", |
1319 | "The event and first entity references passed are both " |
1320 | + "null references.", |
1321 | "Either Event or first entity references must be valid."); |
1322 | return; // no real parameters here anyway |
1323 | } |
1324 | |
1325 | if ((who2 == null) && (what == null)) { |
1326 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1327 | + "Command ignored.", "Scheduler : " + getName() |
1328 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1329 | + "EventOf3Entities what, TimeSpan dt)", |
1330 | "The event and second entity references passed are both " |
1331 | + "null references.", |
1332 | "Either Event or second entity references must be valid."); |
1333 | return; // no real parameters here anyway |
1334 | } |
1335 | |
1336 | if ((who3 == null) && (what == null)) { |
1337 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1338 | + "Command ignored.", "Scheduler : " + getName() |
1339 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1340 | + "EventOf3Entities what, TimeSpan dt)", |
1341 | "The event and third entity references passed are both " |
1342 | + "null references.", |
1343 | "Either Event or third entity references must be valid."); |
1344 | return; // no real parameters here anyway |
1345 | } |
1346 | |
1347 | if (!(who1 instanceof SimProcess) && (what == null)) { |
1348 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1349 | + "Command ignored.", "Scheduler : " + getName() |
1350 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1351 | + "EventOf3Entities what, TimeSpan dt)", |
1352 | "The first entity needs a valid Event to be scheduled with.", |
1353 | "Only SimProcesses may be scheduled without events."); |
1354 | return; // Event needed with Entity |
1355 | } |
1356 | |
1357 | if (!(who2 instanceof SimProcess) && (what == null)) { |
1358 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1359 | + "Command ignored.", "Scheduler : " + getName() |
1360 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1361 | + "EventOf3Entities what, TimeSpan dt)", |
1362 | "The second entity needs a valid Event to be scheduled with.", |
1363 | "Only SimProcesses may be scheduled without events."); |
1364 | return; // Event needed with Entity |
1365 | } |
1366 | |
1367 | if (!(who3 instanceof SimProcess) && (what == null)) { |
1368 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1369 | + "Command ignored.", "Scheduler : " + getName() |
1370 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1371 | + "EventOf3Entities what, TimeSpan dt)", |
1372 | "The third entity needs a valid Event to be scheduled with.", |
1373 | "Only SimProcesses may be scheduled without events."); |
1374 | return; // Event needed with Entity |
1375 | } |
1376 | |
1377 | TimeInstant time = TimeOperations.add(presentTime(), dt); |
1378 | // set time for being scheduled |
1379 | |
1380 | EventNote note = new EventNote(who1, who2, who3, what, time); |
1381 | |
1382 | if (dt == TimeSpan.ZERO) { // preempting schedule for processes |
1383 | if (_currentProcess == null) { // currently Event -> no preemption |
1384 | // inserted as first in the event-list with the current time as |
1385 | // activation |
1386 | evList.insertAsFirst(note); |
1387 | return; |
1388 | } else { // currently SimProcess -> preempt! |
1389 | preemptSimProcess(note); |
1390 | return; |
1391 | } |
1392 | } |
1393 | |
1394 | // all parameters checked, now schedule Event |
1395 | evList.insert(note); |
1396 | |
1397 | } |
1398 | |
1399 | /** |
1400 | * Schedules the event to happen at the specified time. Checks that only |
1401 | * legal combinations of valid parameters are scheduled. |
1402 | * <p> |
1403 | * <DIV align=center> |
1404 | * <TABLE BORDER > |
1405 | * <CAPTION>Valid scheduling types </CAPTION> |
1406 | * <TR> |
1407 | * <TH><DIV align=center>scheduling type</TH> |
1408 | * <TH>Entity object</TH> |
1409 | * <TH>Event object</TH> |
1410 | * </TR> |
1411 | * <TR> |
1412 | * <TH>Event oriented</TH> |
1413 | * <TD>Event or SimProcess</TD> |
1414 | * <TD>Event</TD> |
1415 | * </TR> |
1416 | * <TR> |
1417 | * <TH>process oriented</TH> |
1418 | * <TD>SimProcess</TD> |
1419 | * <TD>null</TD> |
1420 | * </TR> |
1421 | * <TR> |
1422 | * <TH>external event</TH> |
1423 | * <TD>null</TD> |
1424 | * <TD>external event</TD> |
1425 | * </TR> |
1426 | * </TABLE> |
1427 | * </DIV> |
1428 | * |
1429 | * @param who |
1430 | * Entity : The Entity to be scheduled |
1431 | * @param what |
1432 | * Event : The event to manipulate the entity |
1433 | * @param when |
1434 | * TimeInstant : The point in simulation time for the event to |
1435 | * happen |
1436 | */ |
1437 | protected void schedule(Entity who, EventAbstract what, TimeInstant when) { |
1438 | |
1439 | if (when == null) { |
1440 | myExperiment.sendWarning( |
1441 | "Can't schedule Entity and Event at given " |
1442 | + "time! Command ignored.", "Scheduler : " |
1443 | + getName() + " Method: schedule(Entity who, " |
1444 | + "EventAbstract what, TimeInstant when)", |
1445 | "The simulation time reference passed as parameter is a " |
1446 | + "null reference.", |
1447 | "Always make sure to use valid references only."); |
1448 | return; // time missing |
1449 | } |
1450 | |
1451 | if ((who == null) && (what == null)) { |
1452 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1453 | + "Command ignored.", "Scheduler : " + getName() |
1454 | + " Method: schedule(Entity who, " |
1455 | + "EventAbstract what, TimeInstant when)", |
1456 | "The Event and Entity references passed are both " |
1457 | + "null references.", |
1458 | "Either Event or Entity references must be valid."); |
1459 | return; // no real parameters here anyway |
1460 | } |
1461 | |
1462 | if ((who == null) && !(what instanceof ExternalEvent)) { |
1463 | myExperiment.sendWarning("Can't schedule Event! Command ignored.", |
1464 | "Scheduler : " + getName() |
1465 | + " Method: schedule(Entity who, " |
1466 | + "EventAbstract what, TimeInstant when)", |
1467 | "The Entity reference passed is a null reference but the " |
1468 | + "Event references is not an external event.", |
1469 | "If no valid Entity is given, the event must be of type " |
1470 | + "external event."); |
1471 | return; // if no Entity it must be ExternalEvent |
1472 | } |
1473 | |
1474 | if (!(who instanceof SimProcess) && (what == null)) { |
1475 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1476 | + "Command ignored.", "Scheduler : " + getName() |
1477 | + " Method: schedule(Entity who, " |
1478 | + "EventAbstract what, TimeInstant when)", |
1479 | "The Entity needs a valid Event to be scheduled with.", |
1480 | "Only SimProcesses may be scheduled without events."); |
1481 | return; // Event needed with Entity |
1482 | } |
1483 | |
1484 | if (TimeInstant.isBefore(when, this.presentTime())) { |
1485 | myExperiment |
1486 | .sendWarning( |
1487 | "Can't reschedule Schedulable at given time! " |
1488 | + "Command ignored.", |
1489 | "Scheduler : " |
1490 | + getName() |
1491 | + " Method: schedule(Entity who, " |
1492 | + "EventAbstract what, TimeInstant when)", |
1493 | "The instant given is in the past.", |
1494 | "To schedule a Schedulable, use a TimeInstant no earlier than the present time. " |
1495 | + "The present time can be obtained using the " |
1496 | + "presentTime() method."); |
1497 | return; |
1498 | // I can't be scheduled, TimeInstant has already passed. |
1499 | } |
1500 | |
1501 | if(what != null) |
1502 | { |
1503 | if (what.getNumberOfEntities() > 1) |
1504 | { |
1505 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1506 | + "Command ignored.", "Scheduler : " + getName() |
1507 | + " Method: schedule(Entity who, " |
1508 | + "Event what, TimeSpan dt)", |
1509 | "The method needs the correct Event to be scheduled with.", |
1510 | "You are using an event for multiple entities. You need an event for a single entity."); |
1511 | return; // Event needed with Entity |
1512 | } |
1513 | } |
1514 | |
1515 | EventNote note = new EventNote(who, what, when); |
1516 | |
1517 | if (when == presentTime()) { // preempting schedule for processes |
1518 | if (_currentProcess == null) { // currently Event -> no preemption |
1519 | // inserted as first in the event-list with the current time as |
1520 | // activation |
1521 | evList.insertAsFirst(note); |
1522 | return; |
1523 | } else { // currently SimProcess -> preempt! |
1524 | preemptSimProcess(note); |
1525 | return; |
1526 | } |
1527 | |
1528 | } |
1529 | |
1530 | // all parameters checked, now schedule Event |
1531 | evList.insert(note); |
1532 | |
1533 | } |
1534 | |
1535 | /** |
1536 | * Schedules the event to happen at the specified time. Checks that only |
1537 | * legal combinations of valid parameters are scheduled. |
1538 | * <p> |
1539 | * <DIV align=center> |
1540 | * <TABLE BORDER > |
1541 | * <CAPTION>Valid scheduling types </CAPTION> |
1542 | * <TR> |
1543 | * <TH><DIV align=center>scheduling type</TH> |
1544 | * <TH>Entity object</TH> |
1545 | * <TH>Event object</TH> |
1546 | * </TR> |
1547 | * <TR> |
1548 | * <TH>Event oriented</TH> |
1549 | * <TD>Event or SimProcess</TD> |
1550 | * <TD>Event</TD> |
1551 | * </TR> |
1552 | * <TR> |
1553 | * <TH>process oriented</TH> |
1554 | * <TD>SimProcess</TD> |
1555 | * <TD>null</TD> |
1556 | * </TR> |
1557 | * <TR> |
1558 | * <TH>external event</TH> |
1559 | * <TD>null</TD> |
1560 | * <TD>external event</TD> |
1561 | * </TR> |
1562 | * </TABLE> |
1563 | * </DIV> |
1564 | * |
1565 | * @param who1 |
1566 | * Entity : The first entity to be scheduled |
1567 | * |
1568 | * @param who2 |
1569 | * Entity : The second entity to be scheduled |
1570 | * |
1571 | * @param what |
1572 | * EventOf2Entities : The event to manipulate the entity |
1573 | * |
1574 | * @param when |
1575 | * TimeInstant : The point in simulation time for the event to |
1576 | * happen |
1577 | */ |
1578 | protected void schedule(Entity who1, Entity who2, EventOf2Entities<?, ?> what, TimeInstant when) { |
1579 | |
1580 | if (when == null) { |
1581 | myExperiment.sendWarning( |
1582 | "Can't schedule Entity and Event at given " |
1583 | + "time! Command ignored.", "Scheduler : " |
1584 | + getName() + " Method: schedule(Entity who1, Entity who2, " |
1585 | + "EventOf2Entities what, TimeInstant when)", |
1586 | "The simulation time reference passed as parameter is a " |
1587 | + "null reference.", |
1588 | "Always make sure to use valid references only."); |
1589 | return; // time missing |
1590 | } |
1591 | |
1592 | if ((who1 == null) && (what == null)) { |
1593 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1594 | + "Command ignored.", "Scheduler : " + getName() |
1595 | + " Method: schedule(Entity who1, Entity who2, " |
1596 | + "EventOf2Entities what, TimeInstant when)", |
1597 | "The event and first entity references passed are both " |
1598 | + "null references.", |
1599 | "Either Event or first entity references must be valid."); |
1600 | return; // no real parameters here anyway |
1601 | } |
1602 | |
1603 | if ((who2 == null) && (what == null)) { |
1604 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1605 | + "Command ignored.", "Scheduler : " + getName() |
1606 | + " Method: schedule(Entity who1, Entity who2, " |
1607 | + "EventOf2Entities what, TimeInstant when)", |
1608 | "The event and second entity references passed are both " |
1609 | + "null references.", |
1610 | "Either Event or second entity references must be valid."); |
1611 | return; // no real parameters here anyway |
1612 | } |
1613 | |
1614 | if (!(who1 instanceof SimProcess) && (what == null)) { |
1615 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1616 | + "Command ignored.", "Scheduler : " + getName() |
1617 | + " Method: schedule(Entity who1, Entity who2, " |
1618 | + "EventOf2Entities what, TimeInstant when)", |
1619 | "The first entity needs a valid Event to be scheduled with.", |
1620 | "Only SimProcesses may be scheduled without events."); |
1621 | return; // Event needed with Entity |
1622 | } |
1623 | |
1624 | if (!(who2 instanceof SimProcess) && (what == null)) { |
1625 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1626 | + "Command ignored.", "Scheduler : " + getName() |
1627 | + " Method: schedule(Entity who1, Entity who2, " |
1628 | + "EventOf2Entities what, TimeInstant when)", |
1629 | "The second entity needs a valid Event to be scheduled with.", |
1630 | "Only SimProcesses may be scheduled without events."); |
1631 | return; // Event needed with Entity |
1632 | } |
1633 | |
1634 | if (TimeInstant.isBefore(when, this.presentTime())) { |
1635 | myExperiment |
1636 | .sendWarning( |
1637 | "Can't reschedule Schedulable at given time! " |
1638 | + "Command ignored.", |
1639 | "Scheduler : " |
1640 | + getName() |
1641 | + " Method: schedule(Entity who1, Entity who2, EventOf2Entities what, TimeInstant when)", |
1642 | "The instant given is in the past.", |
1643 | "To schedule a Schedulable, use a TimeInstant no earlier than the present time. " |
1644 | + "The present time can be obtained using the " |
1645 | + "presentTime() method."); |
1646 | return; |
1647 | // I can't be scheduled, TimeInstant has already passed. |
1648 | } |
1649 | |
1650 | EventNote note = new EventNote(who1, who2, what, when); |
1651 | |
1652 | if (when == presentTime()) { // preempting schedule for processes |
1653 | if (_currentProcess == null) { // currently Event -> no preemption |
1654 | // inserted as first in the event-list with the current time as |
1655 | // activation |
1656 | evList.insertAsFirst(note); |
1657 | return; |
1658 | } else { // currently SimProcess -> preempt! |
1659 | preemptSimProcess(note); |
1660 | return; |
1661 | } |
1662 | |
1663 | } |
1664 | |
1665 | // all parameters checked, now schedule Event |
1666 | evList.insert(note); |
1667 | |
1668 | } |
1669 | |
1670 | /** |
1671 | * Schedules the event to happen at the specified time. Checks that only |
1672 | * legal combinations of valid parameters are scheduled. |
1673 | * <p> |
1674 | * <DIV align=center> |
1675 | * <TABLE BORDER > |
1676 | * <CAPTION>Valid scheduling types </CAPTION> |
1677 | * <TR> |
1678 | * <TH><DIV align=center>scheduling type</TH> |
1679 | * <TH>Entity object</TH> |
1680 | * <TH>Event object</TH> |
1681 | * </TR> |
1682 | * <TR> |
1683 | * <TH>Event oriented</TH> |
1684 | * <TD>Event or SimProcess</TD> |
1685 | * <TD>Event</TD> |
1686 | * </TR> |
1687 | * <TR> |
1688 | * <TH>process oriented</TH> |
1689 | * <TD>SimProcess</TD> |
1690 | * <TD>null</TD> |
1691 | * </TR> |
1692 | * <TR> |
1693 | * <TH>external event</TH> |
1694 | * <TD>null</TD> |
1695 | * <TD>external event</TD> |
1696 | * </TR> |
1697 | * </TABLE> |
1698 | * </DIV> |
1699 | * |
1700 | * @param who1 |
1701 | * Entity : The first entity to be scheduled |
1702 | * |
1703 | * @param who2 |
1704 | * Entity : The second entity to be scheduled |
1705 | * |
1706 | * @param who3 |
1707 | * Entity : The third entity to be scheduled |
1708 | * |
1709 | * @param what |
1710 | * EventOf3Entities : The event to manipulate the entity |
1711 | * @param when |
1712 | * TimeInstant : The point in simulation time for the event to |
1713 | * happen |
1714 | */ |
1715 | protected void schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what, TimeInstant when) { |
1716 | |
1717 | if (when == null) { |
1718 | myExperiment.sendWarning( |
1719 | "Can't schedule Entity and Event at given " |
1720 | + "time! Command ignored.", "Scheduler : " |
1721 | + getName() + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1722 | + "EventOf3Entities what, TimeInstant when)", |
1723 | "The simulation time reference passed as parameter is a " |
1724 | + "null reference.", |
1725 | "Always make sure to use valid references only."); |
1726 | return; // time missing |
1727 | } |
1728 | |
1729 | if ((who1 == null) && (what == null)) { |
1730 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1731 | + "Command ignored.", "Scheduler : " + getName() |
1732 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1733 | + "EventOf3Entities what, TimeInstant when)", |
1734 | "The first Event and Entity references passed are both " |
1735 | + "null references.", |
1736 | "Either Event or Entity references must be valid."); |
1737 | return; // no real parameters here anyway |
1738 | } |
1739 | |
1740 | if ((who2 == null) && (what == null)) { |
1741 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1742 | + "Command ignored.", "Scheduler : " + getName() |
1743 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1744 | + "EventOf3Entities what, TimeInstant when)", |
1745 | "The EEvent and second entity references passed are both " |
1746 | + "null references.", |
1747 | "Either Event or second entity references must be valid."); |
1748 | return; // no real parameters here anyway |
1749 | } |
1750 | |
1751 | if ((who3 == null) && (what == null)) { |
1752 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1753 | + "Command ignored.", "Scheduler : " + getName() |
1754 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1755 | + "EventOf3Entities what, TimeInstant when)", |
1756 | "The event and third entity references passed are both " |
1757 | + "null references.", |
1758 | "Either Event or third entity references must be valid."); |
1759 | return; // no real parameters here anyway |
1760 | } |
1761 | |
1762 | if (!(who1 instanceof SimProcess) && (what == null)) { |
1763 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1764 | + "Command ignored.", "Scheduler : " + getName() |
1765 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1766 | + "EventOf3Entities what, TimeInstant when)", |
1767 | "The first entity needs a valid Event to be scheduled with.", |
1768 | "Only SimProcesses may be scheduled without events."); |
1769 | return; // Event needed with Entity |
1770 | } |
1771 | |
1772 | if (!(who2 instanceof SimProcess) && (what == null)) { |
1773 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1774 | + "Command ignored.", "Scheduler : " + getName() |
1775 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1776 | + "EventOf3Entities what, TimeInstant when)", |
1777 | "The second entity needs a valid Event to be scheduled with.", |
1778 | "Only SimProcesses may be scheduled without events."); |
1779 | return; // Event needed with Entity |
1780 | } |
1781 | |
1782 | if (!(who3 instanceof SimProcess) && (what == null)) { |
1783 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1784 | + "Command ignored.", "Scheduler : " + getName() |
1785 | + " Method: schedule(Entity who1, Entity who2, Entity who3, " |
1786 | + "EventOf3Entities what, TimeInstant when)", |
1787 | "The third entity needs a valid Event to be scheduled with.", |
1788 | "Only SimProcesses may be scheduled without events."); |
1789 | return; // Event needed with Entity |
1790 | } |
1791 | |
1792 | if (TimeInstant.isBefore(when, this.presentTime())) { |
1793 | myExperiment |
1794 | .sendWarning( |
1795 | "Can't reschedule Schedulable at given time! " |
1796 | + "Command ignored.", |
1797 | "Scheduler : " |
1798 | + getName() |
1799 | + " Method: schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities what, TimeInstant when)", |
1800 | "The instant given is in the past.", |
1801 | "To schedule a Schedulable, use a TimeInstant no earlier than the present time. " |
1802 | + "The present time can be obtained using the " |
1803 | + "presentTime() method."); |
1804 | return; |
1805 | // I can't be scheduled, TimeInstant has already passed. |
1806 | } |
1807 | |
1808 | EventNote note = new EventNote(who1, who2, who3, what, when); |
1809 | |
1810 | if (when == presentTime()) { // preempting schedule for processes |
1811 | if (_currentProcess == null) { // currently Event -> no preemption |
1812 | // inserted as first in the event-list with the current time as |
1813 | // activation |
1814 | evList.insertAsFirst(note); |
1815 | return; |
1816 | } else { // currently SimProcess -> preempt! |
1817 | preemptSimProcess(note); |
1818 | return; |
1819 | } |
1820 | |
1821 | } |
1822 | |
1823 | // all parameters checked, now schedule Event |
1824 | evList.insert(note); |
1825 | |
1826 | } |
1827 | |
1828 | /** |
1829 | * Schedules the given Entity and Event to happen straight after the given |
1830 | * Schedulable is set to be activated. Note that the siulation time for the |
1831 | * newly entered EventNote will be set to the Schedulable's time and the new |
1832 | * EventNote will be inserted directly after the Schedulable's EventNote. |
1833 | * <p> |
1834 | * <DIV align=center> |
1835 | * <TABLE BORDER > |
1836 | * <CAPTION>Valid scheduling types </CAPTION> |
1837 | * <TR> |
1838 | * <TH><DIV align=center>scheduling type</TH> |
1839 | * <TH>Entity object</TH> |
1840 | * <TH>Event object</TH> |
1841 | * </TR> |
1842 | * <TR> |
1843 | * <TH>Event oriented</TH> |
1844 | * <TD>Event or SimProcess</TD> |
1845 | * <TD>Event</TD> |
1846 | * </TR> |
1847 | * <TR> |
1848 | * <TH>process oriented</TH> |
1849 | * <TD>SimProcess</TD> |
1850 | * <TD>null</TD> |
1851 | * </TR> |
1852 | * <TR> |
1853 | * <TH>external event</TH> |
1854 | * <TD>null</TD> |
1855 | * <TD>external event</TD> |
1856 | * </TR> |
1857 | * </TABLE> |
1858 | * </DIV> |
1859 | * |
1860 | * @param after |
1861 | * Schedulable : The Schedulable after which the new event-note is |
1862 | * to be scheduled |
1863 | * @param who |
1864 | * Entity : The Entity to be scheduled |
1865 | * @param what |
1866 | * Event : The event to be scheduled |
1867 | */ |
1868 | protected void scheduleAfter(Schedulable after, Entity who, EventAbstract what) { |
1869 | |
1870 | if (after == null) { |
1871 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
1872 | + "Command ignored.", "Scheduler : " + getName() |
1873 | + " Method: scheduleAfter(Schedulable after " |
1874 | + ", Entity who, EventAbstract what)", |
1875 | "The reference for the Schedulable to schedule after is a " |
1876 | + "null references.", |
1877 | "Always check to use valid references."); |
1878 | return; // relative Schedulable missing |
1879 | } |
1880 | |
1881 | if (!after.isScheduled() && (after != _currentSchedulable)) { |
1882 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
1883 | + "Command ignored.", "Scheduler : " + getName() |
1884 | + " Method: scheduleAfter(Schedulable after " |
1885 | + ", Entity who, EventAbstract what)", |
1886 | "The Schedulable to be scheduled after is not scheduled.", |
1887 | "The Schedulable taken as reference must be scheduled."); |
1888 | return; // relative Schedulable not scheduled |
1889 | } |
1890 | |
1891 | if ((who == null) && (what == null)) { |
1892 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1893 | + "Command ignored.", "Scheduler : " + getName() |
1894 | + " Method: scheduleAfter(Schedulable after " |
1895 | + ", Entity who, EventAbstract what)", |
1896 | "The Event and Entity references passed are both " |
1897 | + "null references.", |
1898 | "Either Event or Entity references must be valid."); |
1899 | return; // no real parameters here anyway |
1900 | } |
1901 | |
1902 | if ((who == null) && !(what instanceof ExternalEvent)) { |
1903 | myExperiment.sendWarning("Can't schedule Event! Command ignored.", |
1904 | "Scheduler : " + getName() |
1905 | + " Method: scheduleAfter(Schedulabe " |
1906 | + "after, Entity who, EventAbstract what)", |
1907 | "The Entity reference passed is a null reference but the " |
1908 | + "Event references is not an external event.", |
1909 | "If no valid Entity is given, the event must be of type " |
1910 | + "external event."); |
1911 | return; // if no Entity it must be ExternalEvent |
1912 | } |
1913 | |
1914 | if (!(who instanceof SimProcess) && (what == null)) { |
1915 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1916 | + "Command ignored.", "Scheduler : " + getName() |
1917 | + " Method: scheduleAfter(Schedulabe " |
1918 | + "after, Entity who, EventAbstract what)", |
1919 | "The Entity needs a valid Event to be scheduled with.", |
1920 | "Only SimProcesses may be scheduled without events."); |
1921 | return; // Event needed with Entity |
1922 | } |
1923 | |
1924 | if(what != null) |
1925 | { |
1926 | if (what.getNumberOfEntities() > 1) |
1927 | { |
1928 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
1929 | + "Command ignored.", "Scheduler : " + getName() |
1930 | + " Method: scheduleAfter(Schedulabe " |
1931 | + "after, Entity who, EventAbstract what)", |
1932 | "The method needs the correct Event to be scheduled with.", |
1933 | "You are using an event for multiple entities. You need an event for a single entity."); |
1934 | return; // Event with only one entity needed |
1935 | } |
1936 | } |
1937 | |
1938 | if (after != _currentSchedulable) { |
1939 | // all parameters checked, now go on and schedule |
1940 | EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1); |
1941 | evList.insertAfter(afterNote, new EventNote(who, what, afterNote |
1942 | .getTime())); |
1943 | // sets the time equivalent to the Schedulable's |
1944 | } else { |
1945 | evList.insertAsFirst(new EventNote(who, what, presentTime())); |
1946 | } |
1947 | |
1948 | } |
1949 | |
1950 | /** |
1951 | * Schedules the given Entity and Event to happen straight after the given |
1952 | * Schedulable is set to be activated. Note that the siulation time for the |
1953 | * newly entered EventNote will be set to the Schedulable's time and the new |
1954 | * EventNote will be inserted directly after the Schedulable's EventNote. |
1955 | * <p> |
1956 | * <DIV align=center> |
1957 | * <TABLE BORDER > |
1958 | * <CAPTION>Valid scheduling types </CAPTION> |
1959 | * <TR> |
1960 | * <TH><DIV align=center>scheduling type</TH> |
1961 | * <TH>Entity object</TH> |
1962 | * <TH>Event object</TH> |
1963 | * </TR> |
1964 | * <TR> |
1965 | * <TH>Event oriented</TH> |
1966 | * <TD>Event or SimProcess</TD> |
1967 | * <TD>Event</TD> |
1968 | * </TR> |
1969 | * <TR> |
1970 | * <TH>process oriented</TH> |
1971 | * <TD>SimProcess</TD> |
1972 | * <TD>null</TD> |
1973 | * </TR> |
1974 | * <TR> |
1975 | * <TH>external event</TH> |
1976 | * <TD>null</TD> |
1977 | * <TD>external event</TD> |
1978 | * </TR> |
1979 | * </TABLE> |
1980 | * </DIV> |
1981 | * |
1982 | * @param after |
1983 | * Schedulable : The Schedulable after which the new event-note is |
1984 | * to be scheduled |
1985 | * @param who1 |
1986 | * Entity : The first entity to be scheduled |
1987 | * |
1988 | * @param who2 |
1989 | * Entity : The second entity to be scheduled |
1990 | * |
1991 | * @param what |
1992 | * EventOf2Entities : The event to be scheduled |
1993 | */ |
1994 | protected void scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities<?, ?> what) { |
1995 | |
1996 | if (after == null) { |
1997 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
1998 | + "Command ignored.", "Scheduler : " + getName() |
1999 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2000 | "The reference for the Schedulable to schedule after is a " |
2001 | + "null references.", |
2002 | "Always check to use valid references."); |
2003 | return; // relative Schedulable missing |
2004 | } |
2005 | |
2006 | if (!after.isScheduled() && (after != _currentSchedulable)) { |
2007 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2008 | + "Command ignored.", "Scheduler : " + getName() |
2009 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2010 | "The Schedulable to be scheduled after is not scheduled.", |
2011 | "The Schedulable taken as reference must be scheduled."); |
2012 | return; // relative Schedulable not scheduled |
2013 | } |
2014 | |
2015 | if ((who1 == null) && (what == null)) { |
2016 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2017 | + "Command ignored.", "Scheduler : " + getName() |
2018 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2019 | "The event and Entity 'who1' references passed are both " |
2020 | + "null references.", |
2021 | "Either Event or Entity 'who1' references must be valid."); |
2022 | return; // no real parameters here anyway |
2023 | } |
2024 | |
2025 | if ((who2 == null) && (what == null)) { |
2026 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2027 | + "Command ignored.", "Scheduler : " + getName() |
2028 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2029 | "The event and Entity 'who2' references passed are both " |
2030 | + "null references.", |
2031 | "Either Event or Entity 'who2' references must be valid."); |
2032 | return; // no real parameters here anyway |
2033 | } |
2034 | |
2035 | if (!(who1 instanceof SimProcess) && (what == null)) { |
2036 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2037 | + "Command ignored.", "Scheduler : " + getName() |
2038 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2039 | "The Entity 'who1' needs a valid Event to be scheduled with.", |
2040 | "Only SimProcesses may be scheduled without events."); |
2041 | return; // Event needed with Entity |
2042 | } |
2043 | |
2044 | if (!(who2 instanceof SimProcess) && (what == null)) { |
2045 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2046 | + "Command ignored.", "Scheduler : " + getName() |
2047 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2048 | "The Entity 'who2' needs a valid Event to be scheduled with.", |
2049 | "Only SimProcesses may be scheduled without events."); |
2050 | return; // Event needed with Entity |
2051 | } |
2052 | |
2053 | if (after != _currentSchedulable) { |
2054 | // all parameters checked, now go on and schedule |
2055 | EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1); |
2056 | evList.insertAfter(afterNote, new EventNote(who1, who2, what, afterNote |
2057 | .getTime())); |
2058 | // sets the time equivalent to the Schedulable's |
2059 | } else { |
2060 | evList.insertAsFirst(new EventNote(who1, who2, what, presentTime())); |
2061 | } |
2062 | |
2063 | } |
2064 | |
2065 | /** |
2066 | * Schedules the given Entity and Event to happen straight after the given |
2067 | * Schedulable is set to be activated. Note that the siulation time for the |
2068 | * newly entered EventNote will be set to the Schedulable's time and the new |
2069 | * EventNote will be inserted directly after the Schedulable's EventNote. |
2070 | * <p> |
2071 | * <DIV align=center> |
2072 | * <TABLE BORDER > |
2073 | * <CAPTION>Valid scheduling types </CAPTION> |
2074 | * <TR> |
2075 | * <TH><DIV align=center>scheduling type</TH> |
2076 | * <TH>Entity object</TH> |
2077 | * <TH>Event object</TH> |
2078 | * </TR> |
2079 | * <TR> |
2080 | * <TH>Event oriented</TH> |
2081 | * <TD>Event or SimProcess</TD> |
2082 | * <TD>Event</TD> |
2083 | * </TR> |
2084 | * <TR> |
2085 | * <TH>process oriented</TH> |
2086 | * <TD>SimProcess</TD> |
2087 | * <TD>null</TD> |
2088 | * </TR> |
2089 | * <TR> |
2090 | * <TH>external event</TH> |
2091 | * <TD>null</TD> |
2092 | * <TD>external event</TD> |
2093 | * </TR> |
2094 | * </TABLE> |
2095 | * </DIV> |
2096 | * |
2097 | * @param after |
2098 | * Schedulable : The Schedulable after which the new event-note is |
2099 | * to be scheduled |
2100 | * @param who1 |
2101 | * Entity : The first entity to be scheduled |
2102 | * |
2103 | * @param who2 |
2104 | * Entity : The second entity to be scheduled |
2105 | * |
2106 | * @param who3 |
2107 | * Entity : The third entity to be scheduled |
2108 | * |
2109 | * @param what |
2110 | * EventOf3Entities : The event to be scheduled |
2111 | */ |
2112 | protected void scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what) { |
2113 | |
2114 | if (after == null) { |
2115 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2116 | + "Command ignored.", "Scheduler : " + getName() |
2117 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2118 | "The reference for the Schedulable to schedule after is a " |
2119 | + "null references.", |
2120 | "Always check to use valid references."); |
2121 | return; // relative Schedulable missing |
2122 | } |
2123 | |
2124 | if (!after.isScheduled() && (after != _currentSchedulable)) { |
2125 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2126 | + "Command ignored.", "Scheduler : " + getName() |
2127 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2128 | "The Schedulable to be scheduled after is not scheduled.", |
2129 | "The Schedulable taken as reference must be scheduled."); |
2130 | return; // relative Schedulable not scheduled |
2131 | } |
2132 | |
2133 | if ((who1 == null) && (what == null)) { |
2134 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2135 | + "Command ignored.", "Scheduler : " + getName() |
2136 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2137 | "The event and Entity 'who1' references passed are both " |
2138 | + "null references.", |
2139 | "Either Event or Entity 'who1' references must be valid."); |
2140 | return; // no real parameters here anyway |
2141 | } |
2142 | |
2143 | if ((who2 == null) && (what == null)) { |
2144 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2145 | + "Command ignored.", "Scheduler : " + getName() |
2146 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2147 | "The event and Entity 'who2' references passed are both " |
2148 | + "null references.", |
2149 | "Either Event or Entity 'who2' references must be valid."); |
2150 | return; // no real parameters here anyway |
2151 | } |
2152 | |
2153 | if ((who3 == null) && (what == null)) { |
2154 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2155 | + "Command ignored.", "Scheduler : " + getName() |
2156 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2157 | "The event and Entity 'who3' references passed are both " |
2158 | + "null references.", |
2159 | "Either Event or Entity 'who3' references must be valid."); |
2160 | return; // no real parameters here anyway |
2161 | } |
2162 | |
2163 | if (!(who1 instanceof SimProcess) && (what == null)) { |
2164 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2165 | + "Command ignored.", "Scheduler : " + getName() |
2166 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2167 | "The Entity 'who1' needs a valid Event to be scheduled with.", |
2168 | "Only SimProcesses may be scheduled without events."); |
2169 | return; // Event needed with Entity |
2170 | } |
2171 | |
2172 | if (!(who2 instanceof SimProcess) && (what == null)) { |
2173 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2174 | + "Command ignored.", "Scheduler : " + getName() |
2175 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2176 | "The Entity 'who2' needs a valid Event to be scheduled with.", |
2177 | "Only SimProcesses may be scheduled without events."); |
2178 | return; // Event needed with Entity |
2179 | } |
2180 | |
2181 | if (!(who3 instanceof SimProcess) && (what == null)) { |
2182 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2183 | + "Command ignored.", "Scheduler : " + getName() |
2184 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2185 | "The Entity 'who3' needs a valid Event to be scheduled with.", |
2186 | "Only SimProcesses may be scheduled without events."); |
2187 | return; // Event needed with Entity |
2188 | } |
2189 | |
2190 | if (after != _currentSchedulable) { |
2191 | // all parameters checked, now go on and schedule |
2192 | EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1); |
2193 | evList.insertAfter(afterNote, new EventNote(who1, who2, who3, what, afterNote |
2194 | .getTime())); |
2195 | // sets the time equivalent to the Schedulable's |
2196 | } else { |
2197 | evList.insertAsFirst(new EventNote(who1, who2, who3, what, presentTime())); |
2198 | } |
2199 | |
2200 | } |
2201 | |
2202 | /** |
2203 | * Schedules the given Entity and Event to happen straight before the given |
2204 | * Schedulable is scheduled. Note that the simulation time for the newly |
2205 | * entered EventNote will be set to the Schedulable's time and the new |
2206 | * EventNote will be inserted directly before the Schedulable's EventNote. |
2207 | * <p> |
2208 | * <DIV align=center> |
2209 | * <TABLE BORDER > |
2210 | * <CAPTION>Valid scheduling types </CAPTION> |
2211 | * <TR> |
2212 | * <TH><DIV align=center>scheduling type</TH> |
2213 | * <TH>Entity object</TH> |
2214 | * <TH>Event object</TH> |
2215 | * </TR> |
2216 | * <TR> |
2217 | * <TH>Event oriented</TH> |
2218 | * <TD>Event or SimProcess</TD> |
2219 | * <TD>Event</TD> |
2220 | * </TR> |
2221 | * <TR> |
2222 | * <TH>process oriented</TH> |
2223 | * <TD>SimProcess</TD> |
2224 | * <TD>null</TD> |
2225 | * </TR> |
2226 | * <TR> |
2227 | * <TH>external event</TH> |
2228 | * <TD>null</TD> |
2229 | * <TD>external event</TD> |
2230 | * </TR> |
2231 | * </TABLE> |
2232 | * </DIV> |
2233 | * |
2234 | * @param before |
2235 | * Schedulable : The Schedulable before which the new event-note |
2236 | * is to be scheduled |
2237 | * @param who |
2238 | * Entity : The Entity to be scheduled |
2239 | * @param what |
2240 | * Event : The event to be scheduled |
2241 | */ |
2242 | protected void scheduleBefore(Schedulable before, Entity who, EventAbstract what) { |
2243 | |
2244 | if (before == null) { |
2245 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2246 | + "Command ignored.", "Scheduler : " + getName() |
2247 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2248 | "The reference for the Schedulable to schedule before is a " |
2249 | + "null references.", |
2250 | "Always check to use valid references."); |
2251 | return; // relative Schedulable missing |
2252 | } |
2253 | |
2254 | if (!before.isScheduled()) { |
2255 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2256 | + "Command ignored.", "Scheduler : " + getName() |
2257 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2258 | "The Schedulable to schedule after is not scheduled.", |
2259 | "The Schedulable taken as reference must be scheduled."); |
2260 | return; // relative Schedulable not scheduled |
2261 | } |
2262 | |
2263 | if ((who == null) && (what == null)) { |
2264 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2265 | + "Command ignored.", "Scheduler : " + getName() |
2266 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2267 | "The Event and Entity references passed are both " |
2268 | + "null references.", |
2269 | "Either Event or Entity references must be valid."); |
2270 | return; // no real parameters here anyway |
2271 | } |
2272 | |
2273 | if ((who == null) && !(what instanceof ExternalEvent)) { |
2274 | myExperiment.sendWarning("Can't schedule Event! Command ignored.", |
2275 | "Scheduler : " + getName() |
2276 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2277 | "The Entity reference passed is a null reference but the " |
2278 | + "Event references is not an external event.", |
2279 | "If no valid Entity is given, the event must be of type " |
2280 | + "external event."); |
2281 | return; // if no Entity it must be ExternalEvent |
2282 | } |
2283 | |
2284 | if (!(who instanceof SimProcess) && (what == null)) { |
2285 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2286 | + "Command ignored.", "Scheduler : " + getName() |
2287 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2288 | "The Entity needs a valid Event to be scheduled with.", |
2289 | "Only SimProcesses may be scheduled without events."); |
2290 | return; // Event needed with Entity |
2291 | } |
2292 | |
2293 | if(what != null) |
2294 | { |
2295 | if (what.getNumberOfEntities() > 1) |
2296 | { |
2297 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2298 | + "Command ignored.", "Scheduler : " + getName() |
2299 | + " Method: Schedulable before, Entity who, EventAbstract what", |
2300 | "The method needs the correct Event to be scheduled with.", |
2301 | "You are using an event for multiple entities. You need an event for a single entity."); |
2302 | return; // Event needed with Entity |
2303 | } |
2304 | } |
2305 | |
2306 | // all parameters checked, now go on and schedule |
2307 | EventNote beforeNote = before.getEventNotes().get(0); |
2308 | evList.insertBefore(beforeNote, new EventNote(who, what, beforeNote |
2309 | .getTime())); |
2310 | // sets the time equivalent to the Schedulable's |
2311 | } |
2312 | |
2313 | |
2314 | /** |
2315 | * Schedules the given Entity and Event to happen straight before the given |
2316 | * Schedulable is scheduled. Note that the simulation time for the newly |
2317 | * entered EventNote will be set to the Schedulable's time and the new |
2318 | * EventNote will be inserted directly before the Schedulable's EventNote. |
2319 | * <p> |
2320 | * <DIV align=center> |
2321 | * <TABLE BORDER > |
2322 | * <CAPTION>Valid scheduling types </CAPTION> |
2323 | * <TR> |
2324 | * <TH><DIV align=center>scheduling type</TH> |
2325 | * <TH>Entity object</TH> |
2326 | * <TH>Event object</TH> |
2327 | * </TR> |
2328 | * <TR> |
2329 | * <TH>Event oriented</TH> |
2330 | * <TD>Event or SimProcess</TD> |
2331 | * <TD>Event</TD> |
2332 | * </TR> |
2333 | * <TR> |
2334 | * <TH>process oriented</TH> |
2335 | * <TD>SimProcess</TD> |
2336 | * <TD>null</TD> |
2337 | * </TR> |
2338 | * <TR> |
2339 | * <TH>external event</TH> |
2340 | * <TD>null</TD> |
2341 | * <TD>external event</TD> |
2342 | * </TR> |
2343 | * </TABLE> |
2344 | * </DIV> |
2345 | * |
2346 | * @param before |
2347 | * Schedulable : The Schedulable before which the new event-note |
2348 | * is to be scheduled |
2349 | * @param who1 |
2350 | * Entity : The first entity to be scheduled |
2351 | * |
2352 | * @param who2 |
2353 | * Entity : The second entity to be scheduled |
2354 | * |
2355 | * @param what |
2356 | * EventOf2Entities : The event to be scheduled |
2357 | */ |
2358 | protected void scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities<?, ?> what) { |
2359 | |
2360 | if (before == null) { |
2361 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2362 | + "Command ignored.", "Scheduler : " + getName() |
2363 | + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities what)", |
2364 | "The reference for the Schedulable to schedule before is a " |
2365 | + "null references.", |
2366 | "Always check to use valid references."); |
2367 | return; // relative Schedulable missing |
2368 | } |
2369 | |
2370 | if (!before.isScheduled()) { |
2371 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2372 | + "Command ignored.", "Scheduler : " + getName() |
2373 | + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities what)", |
2374 | "The Schedulable to schedule after is not scheduled.", |
2375 | "The Schedulable taken as reference must be scheduled."); |
2376 | return; // relative Schedulable not scheduled |
2377 | } |
2378 | |
2379 | if ((who1 == null) && (what == null)) { |
2380 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2381 | + "Command ignored.", "Scheduler : " + getName() |
2382 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2383 | "The event and Entity 'who1' references passed are both " |
2384 | + "null references.", |
2385 | "Either Event or Entity 'who1' references must be valid."); |
2386 | return; // no real parameters here anyway |
2387 | } |
2388 | |
2389 | if ((who2 == null) && (what == null)) { |
2390 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2391 | + "Command ignored.", "Scheduler : " + getName() |
2392 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2393 | "The event and Entity 'who2' references passed are both " |
2394 | + "null references.", |
2395 | "Either Event or Entity 'who2' references must be valid."); |
2396 | return; |
2397 | |
2398 | } |
2399 | |
2400 | if (!(who1 instanceof SimProcess) && (what == null)) { |
2401 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2402 | + "Command ignored.", "Scheduler : " + getName() |
2403 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2404 | "The Entity 'who1' needs a valid Event to be scheduled with.", |
2405 | "Only SimProcesses may be scheduled without events."); |
2406 | return; // Event needed with Entity |
2407 | } |
2408 | |
2409 | if (!(who2 instanceof SimProcess) && (what == null)) { |
2410 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2411 | + "Command ignored.", "Scheduler : " + getName() |
2412 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)", |
2413 | "The Entity 'who2' needs a valid Event to be scheduled with.", |
2414 | "Only SimProcesses may be scheduled without events."); |
2415 | return; // Event needed with Entity |
2416 | } |
2417 | |
2418 | // all parameters checked, now go on and schedule |
2419 | EventNote beforeNote = before.getEventNotes().get(0); |
2420 | evList.insertBefore(beforeNote, new EventNote(who1, who2, what, beforeNote |
2421 | .getTime())); |
2422 | // sets the time equivalent to the Schedulable's |
2423 | } |
2424 | |
2425 | /** |
2426 | * Schedules the given Entity and Event to happen straight before the given |
2427 | * Schedulable is scheduled. Note that the simulation time for the newly |
2428 | * entered EventNote will be set to the Schedulable's time and the new |
2429 | * EventNote will be inserted directly before the Schedulable's EventNote. |
2430 | * <p> |
2431 | * <DIV align=center> |
2432 | * <TABLE BORDER > |
2433 | * <CAPTION>Valid scheduling types </CAPTION> |
2434 | * <TR> |
2435 | * <TH><DIV align=center>scheduling type</TH> |
2436 | * <TH>Entity object</TH> |
2437 | * <TH>Event object</TH> |
2438 | * </TR> |
2439 | * <TR> |
2440 | * <TH>Event oriented</TH> |
2441 | * <TD>Event or SimProcess</TD> |
2442 | * <TD>Event</TD> |
2443 | * </TR> |
2444 | * <TR> |
2445 | * <TH>process oriented</TH> |
2446 | * <TD>SimProcess</TD> |
2447 | * <TD>null</TD> |
2448 | * </TR> |
2449 | * <TR> |
2450 | * <TH>external event</TH> |
2451 | * <TD>null</TD> |
2452 | * <TD>external event</TD> |
2453 | * </TR> |
2454 | * </TABLE> |
2455 | * </DIV> |
2456 | * |
2457 | * @param before |
2458 | * Schedulable : The Schedulable before which the new event-note |
2459 | * is to be scheduled |
2460 | * @param who1 |
2461 | * Entity : The first entity to be scheduled |
2462 | * |
2463 | * @param who2 |
2464 | * Entity : The second entity to be scheduled |
2465 | * |
2466 | * @param who3 |
2467 | * Entity : The third entity to be scheduled |
2468 | * |
2469 | * @param what |
2470 | * EventOf3Entities : The event to be scheduled |
2471 | */ |
2472 | protected void scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what) { |
2473 | |
2474 | if (before == null) { |
2475 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2476 | + "Command ignored.", "Scheduler : " + getName() |
2477 | + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2478 | "The reference for the Schedulable to schedule before is a " |
2479 | + "null references.", |
2480 | "Always check to use valid references."); |
2481 | return; // relative Schedulable missing |
2482 | } |
2483 | |
2484 | if (!before.isScheduled()) { |
2485 | myExperiment.sendWarning("Can't schedule after Schedulable! " |
2486 | + "Command ignored.", "Scheduler : " + getName() |
2487 | + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2488 | "The Schedulable to schedule after is not scheduled.", |
2489 | "The Schedulable taken as reference must be scheduled."); |
2490 | return; // relative Schedulable not scheduled |
2491 | } |
2492 | |
2493 | if ((who1 == null) && (what == null)) { |
2494 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2495 | + "Command ignored.", "Scheduler : " + getName() |
2496 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2497 | "The event and Entity 'who1' references passed are both " |
2498 | + "null references.", |
2499 | "Either Event or Entity 'who1' references must be valid."); |
2500 | return; // no real parameters here anyway |
2501 | } |
2502 | |
2503 | if ((who2 == null) && (what == null)) { |
2504 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2505 | + "Command ignored.", "Scheduler : " + getName() |
2506 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2507 | "The event and Entity 'who2' references passed are both " |
2508 | + "null references.", |
2509 | "Either Event or Entity 'who2' references must be valid."); |
2510 | return; // no real parameters here anyway |
2511 | } |
2512 | |
2513 | if ((who3 == null) && (what == null)) { |
2514 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2515 | + "Command ignored.", "Scheduler : " + getName() |
2516 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2517 | "The event and Entity 'who3' references passed are both " |
2518 | + "null references.", |
2519 | "Either Event or Entity 'who3' references must be valid."); |
2520 | return; // no real parameters here anyway |
2521 | } |
2522 | |
2523 | if (!(who1 instanceof SimProcess) && (what == null)) { |
2524 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2525 | + "Command ignored.", "Scheduler : " + getName() |
2526 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2527 | "The Entity 'who1' needs a valid Event to be scheduled with.", |
2528 | "Only SimProcesses may be scheduled without events."); |
2529 | return; // Event needed with Entity |
2530 | } |
2531 | |
2532 | if (!(who2 instanceof SimProcess) && (what == null)) { |
2533 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2534 | + "Command ignored.", "Scheduler : " + getName() |
2535 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2536 | "The Entity 'who2' needs a valid Event to be scheduled with.", |
2537 | "Only SimProcesses may be scheduled without events."); |
2538 | return; // Event needed with Entity |
2539 | } |
2540 | |
2541 | if (!(who3 instanceof SimProcess) && (what == null)) { |
2542 | myExperiment.sendWarning("Can't schedule Entity and Event! " |
2543 | + "Command ignored.", "Scheduler : " + getName() |
2544 | + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)", |
2545 | "The Entity 'who3' needs a valid Event to be scheduled with.", |
2546 | "Only SimProcesses may be scheduled without events."); |
2547 | return; // Event needed with Entity |
2548 | } |
2549 | |
2550 | // all parameters checked, now go on and schedule |
2551 | EventNote beforeNote = before.getEventNotes().get(0); |
2552 | evList.insertBefore(beforeNote, new EventNote(who1, who2, who3, what, beforeNote |
2553 | .getTime())); |
2554 | // sets the time equivalent to the Schedulable's |
2555 | } |
2556 | |
2557 | /** |
2558 | * Creates and sends a debugnote to the experiment's messagedistributor. |
2559 | * These debugnotes express the internal state of the event-list to visualize |
2560 | * the changes of state to help find bugs. Classes <code>Scheduler</code> |
2561 | * and <code>Queue</code> both produce debugnotes if set to do so |
2562 | * representing the data stored inside them. The information about the |
2563 | * simulation time is extracted from the experiment and must not be given as |
2564 | * a parameter. |
2565 | * |
2566 | * @param description |
2567 | * java.lang.String : The description of the event-list's internal |
2568 | * state to be passed with this debugnote |
2569 | */ |
2570 | void sendDebugNote(String description) { |
2571 | |
2572 | myExperiment.getMessageManager().receive( |
2573 | new DebugNote(myExperiment.getModel(), presentTime(), |
2574 | getName(), description)); |
2575 | |
2576 | } |
2577 | |
2578 | /** |
2579 | * Sets the execution speed rate. |
2580 | * |
2581 | * @param executionSpeedRate |
2582 | * double : the execution speed rate |
2583 | * @author Felix Klueckmann |
2584 | */ |
2585 | protected void setExecutionSpeedRate(double executionSpeedRate) { |
2586 | _lock.lock(); |
2587 | this._executionSpeedRate = executionSpeedRate; |
2588 | this._timeReset = true; |
2589 | _waitSynchCondition.signal(); |
2590 | _lock.unlock(); |
2591 | } |
2592 | |
2593 | /** |
2594 | * Sets the flag indicating if the event-list processes concurrent Events in |
2595 | * random order or not. If a change occurred the event-list has to be |
2596 | * changed accordingly. |
2597 | * |
2598 | * @param randomizing |
2599 | * boolean :<code>true</code> forces random order, |
2600 | * <code>false</code> forces "linear" order |
2601 | * @author Ruth Meyer |
2602 | */ |
2603 | protected void setRandomizingConcurrentEvents(boolean randomizing) { |
2604 | // nothing new? |
2605 | if (this._randomizingConcurrentEvents == randomizing) { |
2606 | return; // just keep everything as is |
2607 | } |
2608 | // ok, we have to change the event-list (oh bother!) |
2609 | this._randomizingConcurrentEvents = randomizing; |
2610 | EventList newList; |
2611 | if (this.evList instanceof EventTreeList) { |
2612 | if (randomizing) { |
2613 | newList = new RandomizingEventTreeList(); |
2614 | } else { |
2615 | newList = new EventTreeList(); |
2616 | } |
2617 | } else { |
2618 | if (randomizing) { |
2619 | newList = new RandomizingEventVector(); |
2620 | } else { |
2621 | newList = new EventVectorList(); |
2622 | } |
2623 | } |
2624 | // copy old list into new list |
2625 | EventNote note = this.evList.firstNote(); |
2626 | while (note != null) { |
2627 | newList.insert(note); |
2628 | note = this.evList.nextNote(note); |
2629 | } |
2630 | this.evList = newList; |
2631 | } |
2632 | |
2633 | /** |
2634 | * Returns the status of the current simulation. Clients should not need to |
2635 | * use this method explicitly. This method is polled by each thread when it |
2636 | * exits a lock to check wether it should continue its lifeCycle() method ot |
2637 | * throw a SimulationFinishedException, which seems to be the only legal way |
2638 | * to break out of the deep call hierarchies and stop the Process' |
2639 | * lifeCycle. |
2640 | * |
2641 | * @return boolean : state of the simulation. False if still running, true |
2642 | * if the simulation has already finished correctly |
2643 | */ |
2644 | boolean simFinished() { |
2645 | |
2646 | return simulationFinished; |
2647 | |
2648 | } |
2649 | |
2650 | /** |
2651 | * Signals that the experiment is stopped. |
2652 | * |
2653 | * @author Felix Klueckmann |
2654 | */ |
2655 | protected void signalStop() { |
2656 | _lock.lock(); |
2657 | this._timeReset = true; |
2658 | _waitSynchCondition.signal(); |
2659 | _lock.unlock(); |
2660 | } |
2661 | |
2662 | /** |
2663 | * Returns a string representation of the current state of the event-list. |
2664 | * The string is built by concatenating all string representations of the |
2665 | * contained entities, events and TimeInstant objects calling their |
2666 | * <code>toString()</code> methods. |
2667 | * |
2668 | * @return java.lang.String : The string representation of the queuelist |
2669 | */ |
2670 | public String toString() { |
2671 | |
2672 | StringBuffer buffer = new StringBuffer(); // strings |
2673 | StringBuffer enBuff = null; // Buffer for Entities |
2674 | EventAbstract evBuff; // Buffer for events |
2675 | |
2676 | TimeInstant tiBuff; // Buffer for Instants |
2677 | |
2678 | buffer.append("At " + this.presentTime()); |
2679 | |
2680 | if (this._currentEvent != null) { |
2681 | buffer.append(" current event ["); |
2682 | if (this._currentEvent.getNumberOfEntities() == 0) { |
2683 | buffer.append("-"); |
2684 | } else { |
2685 | buffer.append(this._currentEntity1); |
2686 | if (this._currentEntity2 != null) buffer.append("," + this._currentEntity2); |
2687 | if (this._currentEntity3 != null) buffer.append("," + this._currentEntity3); |
2688 | } |
2689 | buffer.append("][" + this._currentEvent + "]"); |
2690 | } else if (this._currentProcess != null) { |
2691 | buffer.append(" current process [" + this._currentProcess + "]"); |
2692 | } |
2693 | |
2694 | buffer.append(" <br>EvenList: "); |
2695 | |
2696 | if (evList.isEmpty()) { |
2697 | // if empty, give short note |
2698 | buffer.append("- empty -"); |
2699 | return buffer.toString(); |
2700 | } else { |
2701 | |
2702 | // go thru list and present Event notes |
2703 | int i = 0; // counter for position |
2704 | |
2705 | for (EventNote iNote = evList.firstNote(); iNote != null; iNote = evList |
2706 | .nextNote(iNote)) { // loop thru list |
2707 | |
2708 | buffer.append(i + ":"); |
2709 | i++; // increment counter |
2710 | |
2711 | // set the buffers. This saves some calls to EventNote methods |
2712 | evBuff = iNote.getEvent(); |
2713 | if (evBuff.getNumberOfEntities() > 0) { |
2714 | enBuff = new StringBuffer(iNote.getEntity1().toString()); |
2715 | if (evBuff.getNumberOfEntities() > 1) { |
2716 | enBuff.append("," + iNote.getEntity2()); |
2717 | if (evBuff.getNumberOfEntities() > 2) { |
2718 | enBuff.append("," + iNote.getEntity3()); |
2719 | } |
2720 | |
2721 | } |
2722 | } else { |
2723 | enBuff = null; |
2724 | } |
2725 | tiBuff = iNote.getTime(); |
2726 | |
2727 | // set Entity |
2728 | if (enBuff == null) |
2729 | buffer.append("[-]"); |
2730 | else |
2731 | buffer.append("[" + enBuff.toString() + "]"); |
2732 | // embrace in brackets |
2733 | |
2734 | // set Event |
2735 | if (evBuff == null) |
2736 | buffer.append("[-]"); |
2737 | else |
2738 | buffer.append("[" + evBuff.toString() + "]"); |
2739 | // embrace in brackets |
2740 | |
2741 | // set time |
2742 | if (tiBuff == null) |
2743 | buffer.append("[-]"); // can never happen... |
2744 | else |
2745 | buffer.append("[" + tiBuff.toString() + "]<br>"); |
2746 | // embrace in brackets |
2747 | // and make a linebreak |
2748 | } |
2749 | |
2750 | } |
2751 | // get it to the client who asked for it... |
2752 | return buffer.toString(); |
2753 | } |
2754 | } |