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.exception.ComponentNotRunningException;
15 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
16 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
17 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
18 import cz.cuni.amis.pogamut.base3d.ILockableVisionWorldView;
19 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.BeginMessage;
20 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.EndMessage;
21
22 import java.util.logging.Level;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 @AgentScoped
42 public class UDKLockableWorldView extends UDKWorldView implements ILockableVisionWorldView {
43
44 public static final String WORLDVIEW_DEPENDENCY = "UDKLockableWorldViewDependency";
45
46
47
48
49 private Queue<List<IWorldChangeEvent>> batches = new LinkedList<List<IWorldChangeEvent>>();
50
51
52
53
54 private List<IWorldChangeEvent> currentBatch = new ArrayList<IWorldChangeEvent>();
55
56
57
58
59 private boolean locked = false;
60
61
62
63
64 private boolean beginCame = false;
65
66
67
68
69 private final Object objectMutex = new Object();
70
71 @Inject
72 public UDKLockableWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IMediator mediator, IComponentBus bus, IAgentLogger log) {
73 super(dependencies, mediator, bus, log);
74 }
75
76
77
78
79 public void lock() throws ComponentNotRunningException {
80 if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
81 synchronized(objectMutex) {
82 if (isLocked()) return;
83 locked = true;
84 if (log.isLoggable(Level.FINER)) log.finer("World view locked.");
85 }
86 }
87
88
89
90
91
92 public void unlock() throws ComponentNotRunningException {
93 synchronized(objectMutex) {
94 if (!isLocked()) return;
95 if (log.isLoggable(Level.FINER)) log.finer("World view is being unlocked.");
96 locked = false;
97 for (List<IWorldChangeEvent> batch : batches) {
98 processBatch(batch);
99 }
100 batches.clear();
101 if (log.isLoggable(Level.FINER)) log.finer("World view unlocked.");
102 }
103 }
104
105 public boolean isLocked() {
106 return locked;
107 }
108
109 public boolean hasBatchesToProcess() {
110 return !batches.isEmpty();
111 }
112
113
114
115
116
117
118
119 private void processBatch(List<IWorldChangeEvent> batch) {
120 for (IWorldChangeEvent event : batch) {
121 super.notify(event);
122 }
123 }
124
125
126
127
128 @Override
129 public void notify(IWorldChangeEvent event) {
130 if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
131 synchronized(objectMutex) {
132 if (!beginCame) {
133 if (event instanceof BeginMessage) {
134 beginCame = true;
135 } else {
136 super.notify(event);
137 return;
138 }
139 }
140 if (isLocked()) {
141 if (event instanceof EndMessage) {
142 currentBatch.add(event);
143 batches.add(currentBatch);
144 currentBatch = new ArrayList<IWorldChangeEvent>(currentBatch.size()+20);
145 } else {
146 currentBatch.add(event);
147 }
148 } else {
149 if (event instanceof EndMessage) {
150 currentBatch.add(event);
151 processBatch(currentBatch);
152 currentBatch.clear();
153 } else {
154 currentBatch.add(event);
155 }
156 }
157 }
158 }
159
160
161 }