MATSIM
PlayPauseSimulationControl.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.* *
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2008 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 package org.matsim.core.mobsim.framework;
20 
21 import java.util.concurrent.Phaser;
22 import java.util.concurrent.Semaphore;
23 
30 
38 
39  public enum Status {
40  PAUSE, PLAY
41  }
42 
43  private volatile Status status = Status.PLAY;
44 
45  private final Semaphore access = new Semaphore(1, true);
46 
47  private volatile double localTime = -1;
48 
49  private final Phaser stepDone = new Phaser(1);
50  // I think the way this works (e.g. for bdi-abm-integration; presumably for otfvis) is as follows:
51  // (1) Here, a phaser is constructed, with one participant that now needs to arrive. Also, "pause" is called from code
52  // immediately after creation.
53 
55  PlayPauseMobsimListener playPauseMobsimListener = new PlayPauseMobsimListener();
56  qSim.addQueueSimulationListeners(playPauseMobsimListener);
57  }
58 
61  @Override
63  try {
64  access.acquire();
65  } catch (InterruptedException e) {
66  throw new RuntimeException(e);
67  }
68  }
69 
70  @Override
72  access.release();
73  localTime = (int)event.getSimulationTime();
74  // yy I am not so sure about the "int". kai, nov'17
75  stepDone.arriveAndAwaitAdvance();
76  // This is arrival by one party. If "pause" has been pressed before, we have a second party, and thus do not
77  // advance.
78  }
79 
80  @Override
82  localTime = Double.MAX_VALUE;
83  stepDone.arriveAndDeregister();
84  }
85  }
86 
87  @Override
88  public final void doStep(int time) {
89  if (status == Status.PLAY) {
90  // this may happen when clicking single/multi-step forward buttons while playing in the async mode,
91  // so that combination should be disabled in GUI, michalm
92  throw new IllegalStateException();
93  }
94  while (localTime < time) {
95  stepDone.arriveAndAwaitAdvance();
96  // as long as localTime < time, this acts as the second party, and thus the simulation progresses
97  // otherwise, the doStep method will return.
98  }
99  }
100 
101  @Override
102  public final void pause() {
103  if (status != Status.PAUSE) {
104  stepDone.register();
105  // so when "pause" was hit, there is now a second party registered to the the phaser
106  status = Status.PAUSE;
107  }
108  }
109 
110  @Override
111  public final void play() {
112  if (status != Status.PLAY) {
113  stepDone.arriveAndDeregister();
114  // the second party is de-registered, and thus it will now just play
115 
116  status = Status.PLAY;
117  }
118  }
119 
120  public final Semaphore getAccess() {
121  return access;
122  }
123 
124  public final boolean isFinished() {
125  return (localTime == Double.MAX_VALUE);
126  }
127 
128  public final double getLocalTime() {
129  return localTime;
130  }
131 
132 }
void addQueueSimulationListeners(final MobsimListener listener)