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