1 package cz.cuni.amis.pogamut.ut2004.communication.worldview;
2
3 import java.util.ArrayList;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Queue;
7
8 import com.google.inject.Inject;
9 import com.google.inject.name.Named;
10
11 import cz.cuni.amis.pogamut.base.communication.mediator.IMediator;
12 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
13 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
14 import cz.cuni.amis.pogamut.base.component.bus.event.BusAwareCountDownLatch;
15 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentNotRunningException;
16 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentPausedException;
17 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
18 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
19 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
20 import cz.cuni.amis.pogamut.base3d.ILockableVisionWorldView;
21 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BeginMessage;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
24 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
25 import java.util.logging.Level;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 @AgentScoped
63 public class UT2004SyncLockableWorldView extends UT2004WorldView
64 implements ILockableVisionWorldView {
65
66 public static final String WORLDVIEW_DEPENDENCY = "UT2004SyncLockableWorldViewDependency";
67
68
69
70
71 private Queue<List<IWorldChangeEvent>> batches = new LinkedList<List<IWorldChangeEvent>>();
72
73
74
75
76 private List<IWorldChangeEvent> currentBatch = new ArrayList<IWorldChangeEvent>();
77
78
79
80
81 private boolean locked = false;
82
83
84
85
86
87
88 private boolean inLock = false;
89
90
91
92
93 private boolean beginCame = false;
94
95
96
97
98 private final Object objectMutex = new Object();
99
100
101
102
103 private BusAwareCountDownLatch lockLatch;
104
105
106
107
108 private boolean stopRequested = false;
109
110
111
112
113 private boolean pauseRequested = false;
114
115 @Inject
116 public UT2004SyncLockableWorldView(
117 @Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies,
118 IMediator mediator,
119 IComponentBus bus, IAgentLogger log) {
120 super(dependencies, mediator, bus, log);
121 }
122
123
124
125
126
127
128 public void lock() throws PogamutInterruptedException, ComponentNotRunningException {
129 if (isPaused()) throw new ComponentPausedException(controller.getState().getFlag(), this);
130 if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
131 synchronized (objectMutex) {
132 if (isLocked())
133 return;
134 locked = true;
135 if (log.isLoggable(Level.FINER)) log.finer("World view is being locked.");
136 }
137 if (isPaused()) {
138 if (log.isLoggable(Level.FINER)) log.finer("World view paused, unlocking.");
139 locked = false;
140 throw new ComponentPausedException(controller.getState().getFlag(), this);
141 }
142 if (!isRunning()) {
143 if (log.isLoggable(Level.FINER)) log.finer("World view not running, unlocking.");
144 locked = false;
145 throw new ComponentNotRunningException(controller.getState().getFlag(), this);
146 }
147 lockLatch.await();
148 if (log.isLoggable(Level.FINER)) log.finer("World view locked.");
149 if (pauseRequested) {
150 throw new ComponentPausedException("Component pause requested.", this);
151 }
152 if (stopRequested) {
153 throw new ComponentNotRunningException("Component stop requested.", this);
154 }
155 }
156
157
158
159
160
161 public void unlock() throws ComponentNotRunningException {
162 synchronized (objectMutex) {
163 if (!isLocked())
164 return;
165 locked = false;
166 if (log.isLoggable(Level.FINER)) log.finer("World view is being unlocked.");
167 inLock = false;
168 processBatches();
169 if (log.isLoggable(Level.FINER)) log.finer("World view unlocked.");
170
171 lockLatch = new BusAwareCountDownLatch(1, eventBus, this);
172 }
173 }
174
175 public boolean isLocked() {
176 return locked;
177 }
178
179 public boolean isInLock() {
180 return inLock;
181 }
182
183
184
185
186
187
188 private void processBatches() {
189
190 for (List<IWorldChangeEvent> batch : batches) {
191 processBatch(batch);
192 }
193 batches.clear();
194
195 processBatch(currentBatch);
196 }
197
198
199
200
201
202
203
204
205
206 private void processBatch(List<IWorldChangeEvent> batch) {
207 for (IWorldChangeEvent event : batch) {
208 super.notify(event);
209 }
210 batch.clear();
211 }
212
213
214
215
216 @Override
217 public void notify(IWorldChangeEvent event) {
218
219
220
221
222
223
224
225
226
227
228
229 synchronized (objectMutex) {
230 if (!beginCame) {
231 if (event instanceof BeginMessage) {
232 beginCame = true;
233 } else {
234 super.notify(event);
235 return;
236 }
237 }
238 if (isLocked()) {
239 if (isInLock()) {
240
241
242 if (event instanceof EndMessage) {
243 currentBatch.add(event);
244 batches.add(currentBatch);
245 currentBatch = new ArrayList<IWorldChangeEvent>(
246 currentBatch.size() + 10);
247 } else {
248 currentBatch.add(event);
249 }
250 } else {
251
252 if (event instanceof EndMessage) {
253
254 super.notify(event);
255
256 if (log.isLoggable(Level.FINER)) log.finer("World view in-locked state, raising the lock() latch.");
257 lockLatch.countDown();
258 inLock = true;
259 } else {
260
261 super.notify(event);
262 }
263 }
264 } else {
265 super.notify(event);
266 }
267 }
268 }
269
270 @Override
271 protected void start(boolean startPaused) {
272 super.start(startPaused);
273 lockLatch = new BusAwareCountDownLatch(1, eventBus, this);
274 stopRequested = false;
275 pauseRequested = false;
276 }
277
278 @Override
279 protected void preStop() {
280 super.preStop();
281 synchronized (objectMutex) {
282 stopRequested = true;
283 lockLatch.countDown();
284 }
285 }
286
287 @Override
288 protected void prePause() {
289 super.preStop();
290 synchronized (objectMutex) {
291 pauseRequested = true;
292 lockLatch.countDown();
293 }
294 }
295
296 @Override
297 protected void resume() {
298 super.resume();
299 synchronized(objectMutex) {
300 lockLatch.countDown();
301 lockLatch = new BusAwareCountDownLatch(1, eventBus, this);
302 pauseRequested = false;
303 }
304 }
305
306 @Override
307 protected void stop() {
308 super.stop();
309 synchronized (objectMutex) {
310 stopRequested = true;
311 lockLatch.countDown();
312 }
313 }
314
315 }