001 /*
002 * Copyright (C) 2010 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package com.google.common.util.concurrent;
018
019 import static com.google.common.base.Preconditions.checkNotNull;
020
021 import com.google.common.annotations.Beta;
022 import com.google.common.base.Throwables;
023 import com.google.common.collect.Lists;
024
025 import java.util.ArrayList;
026 import java.util.concurrent.TimeUnit;
027 import java.util.concurrent.locks.Condition;
028 import java.util.concurrent.locks.ReentrantLock;
029
030 import javax.annotation.Nullable;
031 import javax.annotation.concurrent.GuardedBy;
032
033 /**
034 * A synchronization abstraction supporting waiting on arbitrary boolean conditions.
035 *
036 * <p>This class is intended as a replacement for {@link ReentrantLock}. Code using {@code Monitor}
037 * is less error-prone and more readable than code using {@code ReentrantLock}, without significant
038 * performance loss. {@code Monitor} even has the potential for performance gain by optimizing the
039 * evaluation and signaling of conditions.
040 *
041 * <p>A thread is said to <i>occupy</i> a monitor if it has <i>entered</i> the monitor but not yet
042 * <i>left</i>. Only one thread may occupy a given monitor at any moment. A monitor is also
043 * reentrant, so a thread may enter a monitor any number of times, and then must leave the same
044 * number of times. The <i>enter</i> and <i>leave</i> operations have the same synchronization
045 * semantics as the built-in Java language synchronization primitives.
046 *
047 * <p>A call to any of the <i>enter</i> methods with <b>void</b> return type should always be
048 * followed immediately by a <i>try/finally</i> block to ensure that the current thread leaves the
049 * monitor cleanly: <pre> {@code
050 *
051 * monitor.enter();
052 * try {
053 * // do things while occupying the monitor
054 * } finally {
055 * monitor.leave();
056 * }}</pre>
057 *
058 * A call to any of the <i>enter</i> methods with <b>boolean</b> return type should always appear as
059 * the condition of an <i>if</i> statement containing a <i>try/finally</i> block to ensure that the
060 * current thread leaves the monitor cleanly: <pre> {@code
061 *
062 * if (monitor.tryEnter()) {
063 * try {
064 * // do things while occupying the monitor
065 * } finally {
066 * monitor.leave();
067 * }
068 * } else {
069 * // do other things since the monitor was not available
070 * }}</pre>
071 *
072 * <h2>Comparison with {@code synchronized} and {@code ReentrantLock}</h2>
073 *
074 * <p>The following examples show a simple threadsafe holder expressed using {@code synchronized},
075 * {@link ReentrantLock}, and {@code Monitor}.
076 *
077 * <h3>{@code synchronized}</h3>
078 *
079 * <p>This version is the fewest lines of code, largely because the synchronization mechanism used
080 * is built into the language and runtime. But the programmer has to remember to avoid a couple of
081 * common bugs: The {@code wait()} must be inside a {@code while} instead of an {@code if}, and
082 * {@code notifyAll()} must be used instead of {@code notify()} because there are two different
083 * logical conditions being awaited. <pre> {@code
084 *
085 * public class SafeBox<V> {
086 * private V value;
087 *
088 * public synchronized V get() throws InterruptedException {
089 * while (value == null) {
090 * wait();
091 * }
092 * V result = value;
093 * value = null;
094 * notifyAll();
095 * return result;
096 * }
097 *
098 * public synchronized void set(V newValue) throws InterruptedException {
099 * while (value != null) {
100 * wait();
101 * }
102 * value = newValue;
103 * notifyAll();
104 * }
105 * }}</pre>
106 *
107 * <h3>{@code ReentrantLock}</h3>
108 *
109 * <p>This version is much more verbose than the {@code synchronized} version, and still suffers
110 * from the need for the programmer to remember to use {@code while} instead of {@code if}.
111 * However, one advantage is that we can introduce two separate {@code Condition} objects, which
112 * allows us to use {@code signal()} instead of {@code signalAll()}, which may be a performance
113 * benefit. <pre> {@code
114 *
115 * public class SafeBox<V> {
116 * private final ReentrantLock lock = new ReentrantLock();
117 * private final Condition valuePresent = lock.newCondition();
118 * private final Condition valueAbsent = lock.newCondition();
119 * private V value;
120 *
121 * public V get() throws InterruptedException {
122 * lock.lock();
123 * try {
124 * while (value == null) {
125 * valuePresent.await();
126 * }
127 * V result = value;
128 * value = null;
129 * valueAbsent.signal();
130 * return result;
131 * } finally {
132 * lock.unlock();
133 * }
134 * }
135 *
136 * public void set(V newValue) throws InterruptedException {
137 * lock.lock();
138 * try {
139 * while (value != null) {
140 * valueAbsent.await();
141 * }
142 * value = newValue;
143 * valuePresent.signal();
144 * } finally {
145 * lock.unlock();
146 * }
147 * }
148 * }}</pre>
149 *
150 * <h3>{@code Monitor}</h3>
151 *
152 * <p>This version adds some verbosity around the {@code Guard} objects, but removes that same
153 * verbosity, and more, from the {@code get} and {@code set} methods. {@code Monitor} implements the
154 * same efficient signaling as we had to hand-code in the {@code ReentrantLock} version above.
155 * Finally, the programmer no longer has to hand-code the wait loop, and therefore doesn't have to
156 * remember to use {@code while} instead of {@code if}. <pre> {@code
157 *
158 * public class SafeBox<V> {
159 * private final Monitor monitor = new Monitor();
160 * private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) {
161 * public boolean isSatisfied() {
162 * return value != null;
163 * }
164 * };
165 * private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) {
166 * public boolean isSatisfied() {
167 * return value == null;
168 * }
169 * };
170 * private V value;
171 *
172 * public V get() throws InterruptedException {
173 * monitor.enterWhen(valuePresent);
174 * try {
175 * V result = value;
176 * value = null;
177 * return result;
178 * } finally {
179 * monitor.leave();
180 * }
181 * }
182 *
183 * public void set(V newValue) throws InterruptedException {
184 * monitor.enterWhen(valueAbsent);
185 * try {
186 * value = newValue;
187 * } finally {
188 * monitor.leave();
189 * }
190 * }
191 * }}</pre>
192 *
193 * @author Justin T. Sampson
194 * @since 10.0
195 */
196 @Beta
197 public final class Monitor {
198 // TODO: Use raw LockSupport or AbstractQueuedSynchronizer instead of ReentrantLock.
199
200 /**
201 * A boolean condition for which a thread may wait. A {@code Guard} is associated with a single
202 * {@code Monitor}.
203 *
204 * <p>An implementation of this interface must ensure the following:
205 *
206 * <ul>
207 * <li>Calling {@code isSatisfied()} must be thread-safe with its monitor occupied, because the
208 * monitor may check the guard at arbitrary times from a thread occupying the monitor.
209 * <li>Calling {@code isSatisfied()} must not itself have the effect of altering the return value
210 * of this or any other guard's {@code isSatisfied()} method.
211 * <li>No thread that is <i>not</i> occupying the monitor may cause the value returned by {@code
212 * isSatisfied()} to change from true to false.
213 * <li>If any thread that is <i>not</i> occupying the monitor causes the value returned by {@code
214 * isSatisfied()} to change from false to true, {@link Monitor#reevaluateGuards()} must be called
215 * in order to notify any waiting threads.
216 * </ul>
217 *
218 * <p>If a {@code Guard} is passed into any method of a {@code Monitor} other than the one it is
219 * associated with, an {@link IllegalMonitorStateException} is thrown.
220 *
221 * @since 10.0
222 */
223 @Beta
224 public abstract static class Guard {
225
226 final Monitor monitor;
227 final Condition condition;
228
229 @GuardedBy("monitor.lock")
230 int waiterCount = 0;
231
232 protected Guard(Monitor monitor) {
233 this.monitor = checkNotNull(monitor, "monitor");
234 this.condition = monitor.lock.newCondition();
235 }
236
237 /**
238 * Evaluates this guard's boolean condition.
239 */
240 public abstract boolean isSatisfied();
241
242 @Override
243 public final boolean equals(Object other) {
244 // Overridden as final to ensure identity semantics in Monitor.activeGuards.
245 return this == other;
246 }
247
248 @Override
249 public final int hashCode() {
250 // Overridden as final to ensure identity semantics in Monitor.activeGuards.
251 return super.hashCode();
252 }
253
254 }
255
256 /**
257 * The lock underlying this monitor.
258 */
259 private final ReentrantLock lock;
260
261 /**
262 * The guards associated with this monitor that currently have waiters ({@code waiterCount > 0}).
263 * This is an ArrayList rather than, say, a HashSet so that iteration and almost all adds don't
264 * incur any object allocation overhead.
265 */
266 private final ArrayList<Guard> activeGuards = Lists.newArrayListWithCapacity(1);
267
268 /**
269 * Creates a monitor with a non-fair (but fast) ordering policy. Equivalent to {@code
270 * Monitor(false)}.
271 */
272 public Monitor() {
273 this(false);
274 }
275
276 /**
277 * Creates a monitor with the given ordering policy.
278 *
279 * @param fair whether this monitor should use a fair ordering policy rather than a non-fair (but
280 * fast) one
281 */
282 public Monitor(boolean fair) {
283 this.lock = new ReentrantLock(fair);
284 }
285
286 /**
287 * Enters this monitor. Blocks indefinitely.
288 */
289 public void enter() {
290 lock.lock();
291 }
292
293 /**
294 * Enters this monitor. Blocks indefinitely, but may be interrupted.
295 */
296 public void enterInterruptibly() throws InterruptedException {
297 lock.lockInterruptibly();
298 }
299
300 /**
301 * Enters this monitor. Blocks at most the given time.
302 *
303 * @return whether the monitor was entered
304 */
305 public boolean enter(long time, TimeUnit unit) {
306 final ReentrantLock lock = this.lock;
307 long startNanos = System.nanoTime();
308 long timeoutNanos = unit.toNanos(time);
309 long remainingNanos = timeoutNanos;
310 boolean interruptIgnored = false;
311 try {
312 while (true) {
313 try {
314 return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
315 } catch (InterruptedException ignored) {
316 interruptIgnored = true;
317 remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
318 }
319 }
320 } finally {
321 if (interruptIgnored) {
322 Thread.currentThread().interrupt();
323 }
324 }
325 }
326
327 /**
328 * Enters this monitor. Blocks at most the given time, and may be interrupted.
329 *
330 * @return whether the monitor was entered
331 */
332 public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
333 return lock.tryLock(time, unit);
334 }
335
336 /**
337 * Enters this monitor if it is possible to do so immediately. Does not block.
338 *
339 * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
340 *
341 * @return whether the monitor was entered
342 */
343 public boolean tryEnter() {
344 return lock.tryLock();
345 }
346
347 /**
348 * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
349 */
350 public void enterWhen(Guard guard) throws InterruptedException {
351 if (guard.monitor != this) {
352 throw new IllegalMonitorStateException();
353 }
354 final ReentrantLock lock = this.lock;
355 boolean reentrant = lock.isHeldByCurrentThread();
356 lock.lockInterruptibly();
357 try {
358 waitInterruptibly(guard, reentrant);
359 } catch (Throwable throwable) {
360 lock.unlock();
361 throw Throwables.propagate(throwable);
362 }
363 }
364
365 /**
366 * Enters this monitor when the guard is satisfied. Blocks indefinitely.
367 */
368 public void enterWhenUninterruptibly(Guard guard) {
369 if (guard.monitor != this) {
370 throw new IllegalMonitorStateException();
371 }
372 final ReentrantLock lock = this.lock;
373 boolean reentrant = lock.isHeldByCurrentThread();
374 lock.lock();
375 try {
376 waitUninterruptibly(guard, reentrant);
377 } catch (Throwable throwable) {
378 lock.unlock();
379 throw Throwables.propagate(throwable);
380 }
381 }
382
383 /**
384 * Enters this monitor when the guard is satisfied. Blocks at most the given time, including both
385 * the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
386 * interrupted.
387 *
388 * @return whether the monitor was entered
389 */
390 public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
391 if (guard.monitor != this) {
392 throw new IllegalMonitorStateException();
393 }
394 final ReentrantLock lock = this.lock;
395 boolean reentrant = lock.isHeldByCurrentThread();
396 long startNanos = System.nanoTime();
397 if (!lock.tryLock(time, unit)) {
398 return false;
399 }
400 boolean satisfied;
401 try {
402 long remainingNanos = unit.toNanos(time) - (System.nanoTime() - startNanos);
403 satisfied = waitInterruptibly(guard, remainingNanos, reentrant);
404 } catch (Throwable throwable) {
405 lock.unlock();
406 throw Throwables.propagate(throwable);
407 }
408 if (satisfied) {
409 return true;
410 } else {
411 lock.unlock();
412 return false;
413 }
414 }
415
416 /**
417 * Enters this monitor when the guard is satisfied. Blocks at most the given time, including
418 * both the time to acquire the lock and the time to wait for the guard to be satisfied.
419 *
420 * @return whether the monitor was entered
421 */
422 public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
423 if (guard.monitor != this) {
424 throw new IllegalMonitorStateException();
425 }
426 final ReentrantLock lock = this.lock;
427 boolean reentrant = lock.isHeldByCurrentThread();
428 long startNanos = System.nanoTime();
429 long timeoutNanos = unit.toNanos(time);
430 long remainingNanos = timeoutNanos;
431 boolean interruptIgnored = false;
432 try {
433 while (true) {
434 try {
435 if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
436 break;
437 } else {
438 return false;
439 }
440 } catch (InterruptedException ignored) {
441 interruptIgnored = true;
442 } finally {
443 remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
444 }
445 }
446 boolean satisfied;
447 try {
448 satisfied = waitUninterruptibly(guard, remainingNanos, reentrant);
449 } catch (Throwable throwable) {
450 lock.unlock();
451 throw Throwables.propagate(throwable);
452 }
453 if (satisfied) {
454 return true;
455 } else {
456 lock.unlock();
457 return false;
458 }
459 } finally {
460 if (interruptIgnored) {
461 Thread.currentThread().interrupt();
462 }
463 }
464 }
465
466 /**
467 * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
468 * does not wait for the guard to be satisfied.
469 *
470 * @return whether the monitor was entered
471 */
472 public boolean enterIf(Guard guard) {
473 if (guard.monitor != this) {
474 throw new IllegalMonitorStateException();
475 }
476 final ReentrantLock lock = this.lock;
477 lock.lock();
478 boolean satisfied;
479 try {
480 satisfied = guard.isSatisfied();
481 } catch (Throwable throwable) {
482 lock.unlock();
483 throw Throwables.propagate(throwable);
484 }
485 if (satisfied) {
486 return true;
487 } else {
488 lock.unlock();
489 return false;
490 }
491 }
492
493 /**
494 * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
495 * not wait for the guard to be satisfied, and may be interrupted.
496 *
497 * @return whether the monitor was entered
498 */
499 public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
500 if (guard.monitor != this) {
501 throw new IllegalMonitorStateException();
502 }
503 final ReentrantLock lock = this.lock;
504 lock.lockInterruptibly();
505 boolean satisfied;
506 try {
507 satisfied = guard.isSatisfied();
508 } catch (Throwable throwable) {
509 lock.unlock();
510 throw Throwables.propagate(throwable);
511 }
512 if (satisfied) {
513 return true;
514 } else {
515 lock.unlock();
516 return false;
517 }
518 }
519
520 /**
521 * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
522 * lock, but does not wait for the guard to be satisfied.
523 *
524 * @return whether the monitor was entered
525 */
526 public boolean enterIf(Guard guard, long time, TimeUnit unit) {
527 if (guard.monitor != this) {
528 throw new IllegalMonitorStateException();
529 }
530 final ReentrantLock lock = this.lock;
531 if (!enter(time, unit)) {
532 return false;
533 }
534 boolean satisfied;
535 try {
536 satisfied = guard.isSatisfied();
537 } catch (Throwable throwable) {
538 lock.unlock();
539 throw Throwables.propagate(throwable);
540 }
541 if (satisfied) {
542 return true;
543 } else {
544 lock.unlock();
545 return false;
546 }
547 }
548
549 /**
550 * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
551 * lock, but does not wait for the guard to be satisfied, and may be interrupted.
552 *
553 * @return whether the monitor was entered
554 */
555 public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
556 throws InterruptedException {
557 if (guard.monitor != this) {
558 throw new IllegalMonitorStateException();
559 }
560 final ReentrantLock lock = this.lock;
561 if (!lock.tryLock(time, unit)) {
562 return false;
563 }
564 boolean satisfied;
565 try {
566 satisfied = guard.isSatisfied();
567 } catch (Throwable throwable) {
568 lock.unlock();
569 throw Throwables.propagate(throwable);
570 }
571 if (satisfied) {
572 return true;
573 } else {
574 lock.unlock();
575 return false;
576 }
577 }
578
579 /**
580 * Enters this monitor if it is possible to do so immediately and the guard is satisfied. Does not
581 * block acquiring the lock and does not wait for the guard to be satisfied.
582 *
583 * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
584 *
585 * @return whether the monitor was entered
586 */
587 public boolean tryEnterIf(Guard guard) {
588 if (guard.monitor != this) {
589 throw new IllegalMonitorStateException();
590 }
591 final ReentrantLock lock = this.lock;
592 if (!lock.tryLock()) {
593 return false;
594 }
595 boolean satisfied;
596 try {
597 satisfied = guard.isSatisfied();
598 } catch (Throwable throwable) {
599 lock.unlock();
600 throw Throwables.propagate(throwable);
601 }
602 if (satisfied) {
603 return true;
604 } else {
605 lock.unlock();
606 return false;
607 }
608 }
609
610 /**
611 * Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
612 * called only by a thread currently occupying this monitor.
613 */
614 @GuardedBy("lock")
615 public void waitFor(Guard guard) throws InterruptedException {
616 if (guard.monitor != this) {
617 throw new IllegalMonitorStateException();
618 }
619 if (!lock.isHeldByCurrentThread()) {
620 throw new IllegalMonitorStateException();
621 }
622 waitInterruptibly(guard, true);
623 }
624
625 /**
626 * Waits for the guard to be satisfied. Waits indefinitely. May be called only by a thread
627 * currently occupying this monitor.
628 */
629 @GuardedBy("lock")
630 public void waitForUninterruptibly(Guard guard) {
631 if (guard.monitor != this) {
632 throw new IllegalMonitorStateException();
633 }
634 if (!lock.isHeldByCurrentThread()) {
635 throw new IllegalMonitorStateException();
636 }
637 waitUninterruptibly(guard, true);
638 }
639
640 /**
641 * Waits for the guard to be satisfied. Waits at most the given time, and may be interrupted.
642 * May be called only by a thread currently occupying this monitor.
643 *
644 * @return whether the guard is now satisfied
645 */
646 @GuardedBy("lock")
647 public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
648 if (guard.monitor != this) {
649 throw new IllegalMonitorStateException();
650 }
651 if (!lock.isHeldByCurrentThread()) {
652 throw new IllegalMonitorStateException();
653 }
654 return waitInterruptibly(guard, unit.toNanos(time), true);
655 }
656
657 /**
658 * Waits for the guard to be satisfied. Waits at most the given time. May be called only by a
659 * thread currently occupying this monitor.
660 *
661 * @return whether the guard is now satisfied
662 */
663 @GuardedBy("lock")
664 public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
665 if (guard.monitor != this) {
666 throw new IllegalMonitorStateException();
667 }
668 if (!lock.isHeldByCurrentThread()) {
669 throw new IllegalMonitorStateException();
670 }
671 return waitUninterruptibly(guard, unit.toNanos(time), true);
672 }
673
674 /**
675 * Leaves this monitor. May be called only by a thread currently occupying this monitor.
676 */
677 @GuardedBy("lock")
678 public void leave() {
679 final ReentrantLock lock = this.lock;
680 if (!lock.isHeldByCurrentThread()) {
681 throw new IllegalMonitorStateException();
682 }
683 try {
684 signalConditionsOfSatisfiedGuards(null);
685 } finally {
686 lock.unlock();
687 }
688 }
689
690 /**
691 * Forces all guards to be reevaluated so that threads waiting inside the monitor for guards
692 * whose conditions have become true <i>outside</i> of the monitor will be notified.
693 *
694 * <p>This never needs to be called by a thread occupying the monitor, because all other monitor
695 * methods ensure that all guards are evaluated whenever necessary.
696 */
697 public void reevaluateGuards() {
698 final ReentrantLock lock = this.lock;
699 lock.lock();
700 try {
701 signalConditionsOfSatisfiedGuards(null);
702 } finally {
703 lock.unlock();
704 }
705 }
706
707 /**
708 * Returns whether this monitor is using a fair ordering policy.
709 */
710 public boolean isFair() {
711 return lock.isFair();
712 }
713
714 /**
715 * Returns whether this monitor is occupied by any thread. This method is designed for use in
716 * monitoring of the system state, not for synchronization control.
717 */
718 public boolean isOccupied() {
719 return lock.isLocked();
720 }
721
722 /**
723 * Returns whether the current thread is occupying this monitor (has entered more times than it
724 * has left).
725 */
726 public boolean isOccupiedByCurrentThread() {
727 return lock.isHeldByCurrentThread();
728 }
729
730 /**
731 * Returns the number of times the current thread has entered this monitor in excess of the number
732 * of times it has left. Returns 0 if the current thread is not occupying this monitor.
733 */
734 public int getOccupiedDepth() {
735 return lock.getHoldCount();
736 }
737
738 /**
739 * Returns an estimate of the number of threads waiting to enter this monitor. The value is only
740 * an estimate because the number of threads may change dynamically while this method traverses
741 * internal data structures. This method is designed for use in monitoring of the system state,
742 * not for synchronization control.
743 */
744 public int getQueueLength() {
745 return lock.getQueueLength();
746 }
747
748 /**
749 * Returns whether any threads are waiting to enter this monitor. Note that because cancellations
750 * may occur at any time, a {@code true} return does not guarantee that any other thread will ever
751 * enter this monitor. This method is designed primarily for use in monitoring of the system
752 * state.
753 */
754 public boolean hasQueuedThreads() {
755 return lock.hasQueuedThreads();
756 }
757
758 /**
759 * Queries whether the given thread is waiting to enter this monitor. Note that because
760 * cancellations may occur at any time, a {@code true} return does not guarantee that this thread
761 * will ever enter this monitor. This method is designed primarily for use in monitoring of the
762 * system state.
763 */
764 public boolean hasQueuedThread(Thread thread) {
765 return lock.hasQueuedThread(thread);
766 }
767
768 /**
769 * Queries whether any threads are waiting for the given guard to become satisfied. Note that
770 * because timeouts and interrupts may occur at any time, a {@code true} return does not guarantee
771 * that the guard becoming satisfied in the future will awaken any threads. This method is
772 * designed primarily for use in monitoring of the system state.
773 */
774 public boolean hasWaiters(Guard guard) {
775 if (guard.monitor != this) {
776 throw new IllegalMonitorStateException();
777 }
778 lock.lock();
779 try {
780 return guard.waiterCount > 0;
781 } finally {
782 lock.unlock();
783 }
784 }
785
786 /**
787 * Returns an estimate of the number of threads waiting for the given guard to become satisfied.
788 * Note that because timeouts and interrupts may occur at any time, the estimate serves only as an
789 * upper bound on the actual number of waiters. This method is designed for use in monitoring of
790 * the system state, not for synchronization control.
791 */
792 public int getWaitQueueLength(Guard guard) {
793 if (guard.monitor != this) {
794 throw new IllegalMonitorStateException();
795 }
796 lock.lock();
797 try {
798 return guard.waiterCount;
799 } finally {
800 lock.unlock();
801 }
802 }
803
804 @GuardedBy("lock")
805 private void signalConditionsOfSatisfiedGuards(@Nullable Guard interruptedGuard) {
806 final ArrayList<Guard> guards = this.activeGuards;
807 final int guardCount = guards.size();
808 try {
809 for (int i = 0; i < guardCount; i++) {
810 Guard guard = guards.get(i);
811 if ((guard == interruptedGuard) && (guard.waiterCount == 1)) {
812 // That one waiter was just interrupted and is throwing InterruptedException rather than
813 // paying attention to the guard being satisfied, so find another waiter on another guard.
814 continue;
815 }
816 if (guard.isSatisfied()) {
817 guard.condition.signal();
818 return;
819 }
820 }
821 } catch (Throwable throwable) {
822 for (int i = 0; i < guardCount; i++) {
823 Guard guard = guards.get(i);
824 guard.condition.signalAll();
825 }
826 throw Throwables.propagate(throwable);
827 }
828 }
829
830 @GuardedBy("lock")
831 private void incrementWaiters(Guard guard) {
832 int waiters = guard.waiterCount++;
833 if (waiters == 0) {
834 activeGuards.add(guard);
835 }
836 }
837
838 @GuardedBy("lock")
839 private void decrementWaiters(Guard guard) {
840 int waiters = --guard.waiterCount;
841 if (waiters == 0) {
842 activeGuards.remove(guard);
843 }
844 }
845
846 @GuardedBy("lock")
847 private void waitInterruptibly(Guard guard, boolean signalBeforeWaiting)
848 throws InterruptedException {
849 if (!guard.isSatisfied()) {
850 if (signalBeforeWaiting) {
851 signalConditionsOfSatisfiedGuards(null);
852 }
853 incrementWaiters(guard);
854 try {
855 final Condition condition = guard.condition;
856 do {
857 try {
858 condition.await();
859 } catch (InterruptedException interrupt) {
860 try {
861 signalConditionsOfSatisfiedGuards(guard);
862 } catch (Throwable throwable) {
863 Thread.currentThread().interrupt();
864 throw Throwables.propagate(throwable);
865 }
866 throw interrupt;
867 }
868 } while (!guard.isSatisfied());
869 } finally {
870 decrementWaiters(guard);
871 }
872 }
873 }
874
875 @GuardedBy("lock")
876 private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
877 if (!guard.isSatisfied()) {
878 if (signalBeforeWaiting) {
879 signalConditionsOfSatisfiedGuards(null);
880 }
881 incrementWaiters(guard);
882 try {
883 final Condition condition = guard.condition;
884 do {
885 condition.awaitUninterruptibly();
886 } while (!guard.isSatisfied());
887 } finally {
888 decrementWaiters(guard);
889 }
890 }
891 }
892
893 @GuardedBy("lock")
894 private boolean waitInterruptibly(Guard guard, long remainingNanos, boolean signalBeforeWaiting)
895 throws InterruptedException {
896 if (!guard.isSatisfied()) {
897 if (signalBeforeWaiting) {
898 signalConditionsOfSatisfiedGuards(null);
899 }
900 incrementWaiters(guard);
901 try {
902 final Condition condition = guard.condition;
903 do {
904 if (remainingNanos <= 0) {
905 return false;
906 }
907 try {
908 remainingNanos = condition.awaitNanos(remainingNanos);
909 } catch (InterruptedException interrupt) {
910 try {
911 signalConditionsOfSatisfiedGuards(guard);
912 } catch (Throwable throwable) {
913 Thread.currentThread().interrupt();
914 throw Throwables.propagate(throwable);
915 }
916 throw interrupt;
917 }
918 } while (!guard.isSatisfied());
919 } finally {
920 decrementWaiters(guard);
921 }
922 }
923 return true;
924 }
925
926 @GuardedBy("lock")
927 private boolean waitUninterruptibly(Guard guard, long timeoutNanos,
928 boolean signalBeforeWaiting) {
929 if (!guard.isSatisfied()) {
930 long startNanos = System.nanoTime();
931 if (signalBeforeWaiting) {
932 signalConditionsOfSatisfiedGuards(null);
933 }
934 boolean interruptIgnored = false;
935 try {
936 incrementWaiters(guard);
937 try {
938 final Condition condition = guard.condition;
939 long remainingNanos = timeoutNanos;
940 do {
941 if (remainingNanos <= 0) {
942 return false;
943 }
944 try {
945 remainingNanos = condition.awaitNanos(remainingNanos);
946 } catch (InterruptedException ignored) {
947 try {
948 signalConditionsOfSatisfiedGuards(guard);
949 } catch (Throwable throwable) {
950 Thread.currentThread().interrupt();
951 throw Throwables.propagate(throwable);
952 }
953 interruptIgnored = true;
954 remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
955 }
956 } while (!guard.isSatisfied());
957 } finally {
958 decrementWaiters(guard);
959 }
960 } finally {
961 if (interruptIgnored) {
962 Thread.currentThread().interrupt();
963 }
964 }
965 }
966 return true;
967 }
968
969 }