Lines 48-53
Link Here
|
48 |
import java.util.LinkedList; |
48 |
import java.util.LinkedList; |
49 |
import java.util.List; |
49 |
import java.util.List; |
50 |
import java.util.Map; |
50 |
import java.util.Map; |
|
|
51 |
import java.util.concurrent.Executor; |
51 |
import java.util.logging.Level; |
52 |
import java.util.logging.Level; |
52 |
import java.util.logging.Logger; |
53 |
import java.util.logging.Logger; |
53 |
|
54 |
|
Lines 175-180
Link Here
|
175 |
|
176 |
|
176 |
/** protects internal data structures */ |
177 |
/** protects internal data structures */ |
177 |
private /*final*/ Object LOCK; |
178 |
private /*final*/ Object LOCK; |
|
|
179 |
|
180 |
/** wrapper, if any */ |
181 |
private final Executor wrapper; |
178 |
|
182 |
|
179 |
/** threads that - owns or waits for this mutex */ |
183 |
/** threads that - owns or waits for this mutex */ |
180 |
private /*final*/ Map<Thread,ThreadInfo> registeredThreads; |
184 |
private /*final*/ Map<Thread,ThreadInfo> registeredThreads; |
Lines 200-211
Link Here
|
200 |
*/ |
204 |
*/ |
201 |
public Mutex(Object lock) { |
205 |
public Mutex(Object lock) { |
202 |
init(lock); |
206 |
init(lock); |
|
|
207 |
this.wrapper = null; |
203 |
} |
208 |
} |
204 |
|
209 |
|
205 |
/** Default constructor. |
210 |
/** Default constructor. |
206 |
*/ |
211 |
*/ |
207 |
public Mutex() { |
212 |
public Mutex() { |
208 |
init(new InternalLock()); |
213 |
init(new InternalLock()); |
|
|
214 |
this.wrapper = null; |
209 |
} |
215 |
} |
210 |
|
216 |
|
211 |
/** @param privileged can enter privileged states of this Mutex |
217 |
/** @param privileged can enter privileged states of this Mutex |
Lines 218-223
Link Here
|
218 |
init(new InternalLock()); |
224 |
init(new InternalLock()); |
219 |
privileged.setParent(this); |
225 |
privileged.setParent(this); |
220 |
} |
226 |
} |
|
|
227 |
this.wrapper = null; |
228 |
} |
229 |
|
230 |
/** Constructor for those who wish to do some custom additional tasks |
231 |
* whenever an action or runnable is executed in the {@link Mutex}. This |
232 |
* may be useful for wrapping all the actions with custom {@link ThreadLocal} |
233 |
* value, etc. Just implement the {@link Executor}'s <code>execute(Runnable)</code> |
234 |
* method and do pre and post initialization tasks before running the runnable. |
235 |
* <p> |
236 |
* The {@link Executor#execute} method shall return only when the passed in |
237 |
* {@link Runnable} is finished, otherwise methods like {@link Mutex#readAccess(Action)} and co. |
238 |
* might not return proper result. |
239 |
* |
240 |
* @param privileged can enter privileged states of this Mutex |
241 |
* @param executor allows to wrap the work of the mutex with a custom code |
242 |
* @since 7.12 |
243 |
*/ |
244 |
public Mutex(Privileged privileged, Executor executor) { |
245 |
LOCK = new Mutex(privileged); |
246 |
this.wrapper = executor; |
221 |
} |
247 |
} |
222 |
|
248 |
|
223 |
/** Initiates this Mutex */ |
249 |
/** Initiates this Mutex */ |
Lines 236-242
Link Here
|
236 |
* @param action the action to perform |
262 |
* @param action the action to perform |
237 |
* @return the object returned from {@link Mutex.Action#run} |
263 |
* @return the object returned from {@link Mutex.Action#run} |
238 |
*/ |
264 |
*/ |
239 |
public <T> T readAccess(Action<T> action) { |
265 |
public <T> T readAccess(final Action<T> action) { |
240 |
if (this == EVENT) { |
266 |
if (this == EVENT) { |
241 |
try { |
267 |
try { |
242 |
return doEventAccess(action); |
268 |
return doEventAccess(action); |
Lines 244-249
Link Here
|
244 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
270 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
245 |
} |
271 |
} |
246 |
} |
272 |
} |
|
|
273 |
if (wrapper != null) { |
274 |
try { |
275 |
return doWrapperAccess(action, null, true); |
276 |
} catch (MutexException e) { |
277 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
278 |
} |
279 |
} |
247 |
|
280 |
|
248 |
Thread t = Thread.currentThread(); |
281 |
Thread t = Thread.currentThread(); |
249 |
readEnter(t); |
282 |
readEnter(t); |
Lines 279-288
Link Here
|
279 |
* @exception RuntimeException if any runtime exception is thrown from the run method |
312 |
* @exception RuntimeException if any runtime exception is thrown from the run method |
280 |
* @see #readAccess(Mutex.Action) |
313 |
* @see #readAccess(Mutex.Action) |
281 |
*/ |
314 |
*/ |
282 |
public <T> T readAccess(ExceptionAction<T> action) throws MutexException { |
315 |
public <T> T readAccess(final ExceptionAction<T> action) throws MutexException { |
283 |
if (this == EVENT) { |
316 |
if (this == EVENT) { |
284 |
return doEventAccess(action); |
317 |
return doEventAccess(action); |
285 |
} |
318 |
} |
|
|
319 |
if (wrapper != null) { |
320 |
return doWrapperAccess(action, null, true); |
321 |
} |
286 |
|
322 |
|
287 |
Thread t = Thread.currentThread(); |
323 |
Thread t = Thread.currentThread(); |
288 |
readEnter(t); |
324 |
readEnter(t); |
Lines 310-315
Link Here
|
310 |
|
346 |
|
311 |
return; |
347 |
return; |
312 |
} |
348 |
} |
|
|
349 |
if (wrapper != null) { |
350 |
try { |
351 |
doWrapperAccess(null, action, true); |
352 |
return; |
353 |
} catch (MutexException ex) { |
354 |
throw (IllegalStateException)new IllegalStateException().initCause(ex); |
355 |
} |
356 |
} |
313 |
|
357 |
|
314 |
Thread t = Thread.currentThread(); |
358 |
Thread t = Thread.currentThread(); |
315 |
readEnter(t); |
359 |
readEnter(t); |
Lines 335-340
Link Here
|
335 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
379 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
336 |
} |
380 |
} |
337 |
} |
381 |
} |
|
|
382 |
if (wrapper != null) { |
383 |
try { |
384 |
return doWrapperAccess(action, null, false); |
385 |
} catch (MutexException e) { |
386 |
throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N |
387 |
} |
388 |
} |
338 |
|
389 |
|
339 |
Thread t = Thread.currentThread(); |
390 |
Thread t = Thread.currentThread(); |
340 |
writeEnter(t); |
391 |
writeEnter(t); |
Lines 371-376
Link Here
|
371 |
if (this == EVENT) { |
422 |
if (this == EVENT) { |
372 |
return doEventAccess(action); |
423 |
return doEventAccess(action); |
373 |
} |
424 |
} |
|
|
425 |
if (wrapper != null) { |
426 |
return doWrapperAccess(action, null, false); |
427 |
} |
374 |
|
428 |
|
375 |
Thread t = Thread.currentThread(); |
429 |
Thread t = Thread.currentThread(); |
376 |
writeEnter(t); |
430 |
writeEnter(t); |
Lines 399-404
Link Here
|
399 |
|
453 |
|
400 |
return; |
454 |
return; |
401 |
} |
455 |
} |
|
|
456 |
if (wrapper != null) { |
457 |
try { |
458 |
doWrapperAccess(null, action, false); |
459 |
} catch (MutexException ex) { |
460 |
throw (IllegalStateException)new IllegalStateException().initCause(ex); |
461 |
} |
462 |
return; |
463 |
} |
402 |
|
464 |
|
403 |
Thread t = Thread.currentThread(); |
465 |
Thread t = Thread.currentThread(); |
404 |
writeEnter(t); |
466 |
writeEnter(t); |
Lines 431-436
Link Here
|
431 |
if (this == EVENT) { |
493 |
if (this == EVENT) { |
432 |
return javax.swing.SwingUtilities.isEventDispatchThread(); |
494 |
return javax.swing.SwingUtilities.isEventDispatchThread(); |
433 |
} |
495 |
} |
|
|
496 |
if (wrapper != null) { |
497 |
Mutex m = (Mutex)LOCK; |
498 |
return m.isReadAccess(); |
499 |
} |
434 |
|
500 |
|
435 |
Thread t = Thread.currentThread(); |
501 |
Thread t = Thread.currentThread(); |
436 |
ThreadInfo info; |
502 |
ThreadInfo info; |
Lines 460-465
Link Here
|
460 |
if (this == EVENT) { |
526 |
if (this == EVENT) { |
461 |
return javax.swing.SwingUtilities.isEventDispatchThread(); |
527 |
return javax.swing.SwingUtilities.isEventDispatchThread(); |
462 |
} |
528 |
} |
|
|
529 |
if (wrapper != null) { |
530 |
Mutex m = (Mutex)LOCK; |
531 |
return m.isWriteAccess(); |
532 |
} |
463 |
|
533 |
|
464 |
Thread t = Thread.currentThread(); |
534 |
Thread t = Thread.currentThread(); |
465 |
ThreadInfo info; |
535 |
ThreadInfo info; |
Lines 492-498
Link Here
|
492 |
* @param run runnable to run |
562 |
* @param run runnable to run |
493 |
*/ |
563 |
*/ |
494 |
public void postReadRequest(final Runnable run) { |
564 |
public void postReadRequest(final Runnable run) { |
495 |
postRequest(S, run); |
565 |
postRequest(S, run, null); |
496 |
} |
566 |
} |
497 |
|
567 |
|
498 |
/** Posts a write request. This request runs immediately iff |
568 |
/** Posts a write request. This request runs immediately iff |
Lines 509-515
Link Here
|
509 |
* @param run runnable to run |
579 |
* @param run runnable to run |
510 |
*/ |
580 |
*/ |
511 |
public void postWriteRequest(Runnable run) { |
581 |
public void postWriteRequest(Runnable run) { |
512 |
postRequest(X, run); |
582 |
postRequest(X, run, null); |
513 |
} |
583 |
} |
514 |
|
584 |
|
515 |
/** toString */ |
585 |
/** toString */ |
Lines 1128-1141
Link Here
|
1128 |
* @param mutexMode mutex mode for which the action is rquested |
1198 |
* @param mutexMode mutex mode for which the action is rquested |
1129 |
* @param run the action |
1199 |
* @param run the action |
1130 |
*/ |
1200 |
*/ |
1131 |
private void postRequest(int mutexMode, Runnable run) { |
1201 |
private void postRequest(final int mutexMode, final Runnable run, Executor exec) { |
1132 |
if (this == EVENT) { |
1202 |
if (this == EVENT) { |
1133 |
doEventRequest(run); |
1203 |
doEventRequest(run); |
1134 |
|
1204 |
|
1135 |
return; |
1205 |
return; |
1136 |
} |
1206 |
} |
|
|
1207 |
if (wrapper != null) { |
1208 |
Mutex m = (Mutex)LOCK; |
1209 |
m.postRequest(mutexMode, run, wrapper); |
1210 |
return; |
1211 |
} |
1137 |
|
1212 |
|
1138 |
Thread t = Thread.currentThread(); |
1213 |
final Thread t = Thread.currentThread(); |
1139 |
ThreadInfo info; |
1214 |
ThreadInfo info; |
1140 |
|
1215 |
|
1141 |
synchronized (LOCK) { |
1216 |
synchronized (LOCK) { |
Lines 1156-1163
Link Here
|
1156 |
|
1231 |
|
1157 |
// this mutex is not held |
1232 |
// this mutex is not held |
1158 |
if (info == null) { |
1233 |
if (info == null) { |
|
|
1234 |
if (exec != null) { |
1235 |
class Exec implements Runnable { |
1236 |
public void run() { |
1237 |
enter(mutexMode, t, true); |
1238 |
try { |
1239 |
run.run(); |
1240 |
} finally { |
1241 |
leave(t); |
1242 |
} |
1243 |
} |
1244 |
} |
1245 |
exec.execute(new Exec()); |
1246 |
return; |
1247 |
} |
1248 |
|
1159 |
enter(mutexMode, t, true); |
1249 |
enter(mutexMode, t, true); |
1160 |
|
|
|
1161 |
try { |
1250 |
try { |
1162 |
run.run(); |
1251 |
run.run(); |
1163 |
} finally { |
1252 |
} finally { |
Lines 1192-1197
Link Here
|
1192 |
private boolean canUpgrade(int threadGranted, int requested) { |
1281 |
private boolean canUpgrade(int threadGranted, int requested) { |
1193 |
return (threadGranted == S) && (requested == X) && (readersNo == 1); |
1282 |
return (threadGranted == S) && (requested == X) && (readersNo == 1); |
1194 |
} |
1283 |
} |
|
|
1284 |
|
1285 |
// -------------------------------- WRAPPERS -------------------------------- |
1286 |
|
1287 |
private <T> T doWrapperAccess( |
1288 |
final ExceptionAction<T> action, final Runnable runnable, final boolean readOnly |
1289 |
) throws MutexException { |
1290 |
class R implements Runnable { |
1291 |
T ret; |
1292 |
MutexException e; |
1293 |
|
1294 |
public void run() { |
1295 |
Mutex m = (Mutex)LOCK; |
1296 |
try { |
1297 |
if (readOnly) { |
1298 |
if (action != null) { |
1299 |
ret = m.readAccess(action); |
1300 |
} else { |
1301 |
m.readAccess(runnable); |
1302 |
} |
1303 |
} else { |
1304 |
if (action != null) { |
1305 |
ret = m.writeAccess(action); |
1306 |
} else { |
1307 |
m.writeAccess(runnable); |
1308 |
} |
1309 |
} |
1310 |
} catch (MutexException ex) { |
1311 |
this.e = ex; |
1312 |
} |
1313 |
} |
1314 |
} |
1315 |
R run = new R(); |
1316 |
wrapper.execute(run); |
1317 |
if (run.e != null) { |
1318 |
throw run.e; |
1319 |
} |
1320 |
return run.ret; |
1321 |
} |
1195 |
|
1322 |
|
1196 |
// ------------------------------- EVENT METHODS ---------------------------- |
1323 |
// ------------------------------- EVENT METHODS ---------------------------- |
1197 |
|
1324 |
|
Lines 1484-1490
Link Here
|
1484 |
notifyAll(); |
1611 |
notifyAll(); |
1485 |
} |
1612 |
} |
1486 |
} |
1613 |
} |
1487 |
|
1614 |
|
1488 |
/** Provides access to Mutex's internal methods. |
1615 |
/** Provides access to Mutex's internal methods. |
1489 |
* |
1616 |
* |
1490 |
* This class can be used when one wants to avoid creating a |
1617 |
* This class can be used when one wants to avoid creating a |