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 }