1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import java.util.IdentityHashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.NoSuchElementException;
23 import java.util.concurrent.atomic.AtomicInteger;
24
25
26
27
28
29
30
31 public class SynchronizedArithmetic extends JexlArithmetic {
32
33
34
35
36
37 public abstract static class AbstractMonitor {
38
39 private final AtomicInteger enters = new AtomicInteger();
40
41 private final AtomicInteger exits = new AtomicInteger();
42
43
44
45
46
47 public int getCount() {
48 return enters.get();
49 }
50
51
52
53
54
55 public boolean isBalanced() {
56 return enters.get() == exits.get();
57 }
58
59
60
61
62
63 protected void monitorEnter(final Object o) {
64 enters.incrementAndGet();
65 }
66
67
68
69
70
71 protected void monitorExit(final Object o) {
72 exits.incrementAndGet();
73 }
74
75 }
76
77
78
79
80 static class SafeMonitor extends AbstractMonitor {
81 private final Map<Object, Object> monitored = new IdentityHashMap<>();
82
83 @Override
84 protected void monitorEnter(final Object o) {
85 Object guard;
86 try {
87 while (true) {
88 synchronized (monitored) {
89 guard = monitored.get(o);
90 if (guard == null) {
91 guard = new Object();
92 monitored.put(o, guard);
93 super.monitorEnter(o);
94 break;
95 }
96 }
97 synchronized (guard) {
98 guard.wait();
99 }
100 }
101 } catch (final InterruptedException xint) {
102
103 }
104 }
105
106 @Override protected void monitorExit(final Object o) {
107 final Object guard;
108 synchronized(monitored) {
109 guard = monitored.remove(o);
110 }
111 if (guard != null) {
112 synchronized(guard) {
113 guard.notifyAll();
114 }
115 super.monitorExit(o);
116 }
117 }
118 }
119
120
121
122
123
124 public class SynchronizedIterator implements Iterator<Object> {
125 private final Object monitored;
126 private Iterator<Object> iterator;
127
128 SynchronizedIterator(final Object locked, final Iterator<Object> ii) {
129 monitored = locked;
130 abstractMonitor.monitorEnter(monitored);
131 try {
132 iterator = ii;
133 } finally {
134 if (iterator == null) {
135 abstractMonitor.monitorExit(monitored);
136 }
137 }
138 }
139
140
141 public void close() {
142 if (iterator != null) {
143 abstractMonitor.monitorExit(monitored);
144 iterator = null;
145 }
146 }
147
148 @Override
149 protected void finalize() throws Throwable {
150 close();
151 super.finalize();
152 }
153
154 @Override
155 public boolean hasNext() {
156 if (iterator == null) {
157 return false;
158 }
159 final boolean n = iterator.hasNext();
160 if (!n) {
161 close();
162 }
163 return n;
164 }
165
166 @Override
167 public Object next() {
168 if (iterator == null) {
169 throw new NoSuchElementException();
170 }
171 return iterator.next();
172 }
173
174 @Override
175 public void remove() {
176 if (iterator != null) {
177 iterator.remove();
178 }
179 }
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 private final AbstractMonitor abstractMonitor;
215
216
217
218
219
220
221 protected SynchronizedArithmetic(final AbstractMonitor abstractMonitor, final boolean strict) {
222 super(strict);
223 this.abstractMonitor = abstractMonitor;
224 }
225
226
227
228
229
230
231
232
233 public Object arrayGet(final Map<?, ?> map, final Object key) {
234 abstractMonitor.monitorEnter(map);
235 try {
236 return map.get(key);
237 } finally {
238 abstractMonitor.monitorExit(map);
239 }
240 }
241
242
243
244
245
246
247
248 public void arraySet(final Map<Object, Object> map, final Object key, final Object value) {
249 abstractMonitor.monitorEnter(map);
250 try {
251 map.put(key, value);
252 } finally {
253 abstractMonitor.monitorExit(map);
254 }
255 }
256
257
258
259
260
261 public Iterator<Object> forEach(final Map<Object, Object> map) {
262 return new SynchronizedIterator(map, map.values().iterator());
263 }
264
265
266
267
268
269
270
271
272
273 public Object propertyGet(final Map<?, ?> map, final Object key) {
274 abstractMonitor.monitorEnter(map);
275 try {
276 return map.get(key);
277 } finally {
278 abstractMonitor.monitorExit(map);
279 }
280 }
281
282
283
284
285
286
287
288
289 public void propertySet(final Map<Object, Object> map, final Object key, final Object value) {
290 abstractMonitor.monitorEnter(map);
291 try {
292 map.put(key, value);
293 } finally {
294 abstractMonitor.monitorExit(map);
295 }
296 }
297 }