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