1 package cz.cuni.amis.utils.future;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.concurrent.CountDownLatch;
6 import java.util.concurrent.TimeUnit;
7
8 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
9 import cz.cuni.amis.utils.flag.Flag;
10 import cz.cuni.amis.utils.flag.FlagListener;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public class FlagFuture<Result, FlagType> implements IFuture<Result>, FlagListener<FlagType>{
26
27
28
29
30
31 private Map<FlagType, Result> terminalMap;
32
33
34
35
36 private Flag<FlagType> waitFlag;
37
38
39
40
41 private final CountDownLatch latch = new CountDownLatch(1);
42
43
44
45
46
47 private boolean done = false;
48
49
50
51
52
53 private Result result = null;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public FlagFuture(Flag<FlagType> waitFlag, Map<FlagType, Result> terminalMap) {
72 this.terminalMap = new HashMap<FlagType, Result>(terminalMap);
73 this.waitFlag = waitFlag;
74 init();
75 }
76
77
78
79
80
81
82
83
84 public FlagFuture(Flag<FlagType> waitFlag, FlagType terminalFlagValue, Result resultValue) {
85 terminalMap = new HashMap<FlagType, Result>();
86 terminalMap.put(terminalFlagValue, resultValue);
87 this.waitFlag = waitFlag;
88 init();
89 }
90
91
92
93
94
95
96 private void init() {
97 waitFlag.addListener(this);
98 synchronized(latch) {
99 if (!done) {
100 FlagType value = waitFlag.getFlag();
101 if (terminalMap.containsKey(value)) {
102 result = terminalMap.get(value);
103 done = true;
104 latch.countDown();
105 }
106 }
107 }
108 if (done) waitFlag.removeListener(this);
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public void stop(Result result) {
124 synchronized(latch) {
125 if (done) return;
126 done = true;
127 this.result = result;
128 }
129 waitFlag.removeListener(this);
130 latch.countDown();
131 }
132
133 @Override
134 public boolean cancel(boolean mayInterruptIfRunning) {
135
136 return false;
137 }
138
139 @Override
140 public Result get() {
141 try {
142 latch.await();
143 } catch (InterruptedException e) {
144 throw new PogamutInterruptedException(e.getMessage(), e, this);
145 }
146 return result;
147 }
148
149 @Override
150 public Result get(long timeout, TimeUnit unit) {
151 try {
152 latch.await(timeout, unit);
153 } catch (InterruptedException e) {
154 throw new PogamutInterruptedException(e.getMessage(), e, this);
155 }
156 return result;
157 }
158
159 @Override
160 public boolean isCancelled() {
161 return false;
162 }
163
164 @Override
165 public boolean isDone() {
166 return done;
167 }
168
169 @Override
170 public void flagChanged(FlagType changedValue) {
171 synchronized(latch) {
172 if (done) {
173 waitFlag.removeListener(this);
174 return;
175 }
176 if (terminalMap.containsKey(changedValue)) {
177 result = terminalMap.get(changedValue);
178 done = true;
179 waitFlag.removeListener(this);
180 latch.countDown();
181 }
182 }
183 }
184 }