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        @Override
240        public final boolean equals(Object other) {
241          // Overridden as final to ensure identity semantics in Monitor.activeGuards.
242          return this == other;
243        }
244        
245        @Override
246        public final int hashCode() {
247          // Overridden as final to ensure identity semantics in Monitor.activeGuards.
248          return super.hashCode();
249        }
250    
251      }
252    
253      /**
254       * Whether this monitor is fair.
255       */
256      private final boolean fair;
257      
258      /**
259       * The lock underlying this monitor.
260       */
261      private final ReentrantLock lock;
262    
263      /**
264       * The guards associated with this monitor that currently have waiters ({@code waiterCount > 0}).
265       * This is an ArrayList rather than, say, a HashSet so that iteration and almost all adds don't
266       * incur any object allocation overhead.
267       */
268      @GuardedBy("lock")
269      private final ArrayList<Guard> activeGuards = Lists.newArrayListWithCapacity(1);
270    
271      /**
272       * Creates a monitor with a non-fair (but fast) ordering policy. Equivalent to {@code
273       * Monitor(false)}.
274       */
275      public Monitor() {
276        this(false);
277      }
278    
279      /**
280       * Creates a monitor with the given ordering policy.
281       *
282       * @param fair whether this monitor should use a fair ordering policy rather than a non-fair (but
283       *        fast) one
284       */
285      public Monitor(boolean fair) {
286        this.fair = fair;
287        this.lock = new ReentrantLock(fair);
288      }
289    
290      /**
291       * Enters this monitor. Blocks indefinitely.
292       */
293      public void enter() {
294        lock.lock();
295      }
296    
297      /**
298       * Enters this monitor. Blocks indefinitely, but may be interrupted.
299       */
300      public void enterInterruptibly() throws InterruptedException {
301        lock.lockInterruptibly();
302      }
303    
304      /**
305       * Enters this monitor. Blocks at most the given time.
306       *
307       * @return whether the monitor was entered
308       */
309      public boolean enter(long time, TimeUnit unit) {
310        final ReentrantLock lock = this.lock;
311        if (!fair && lock.tryLock()) {
312          return true;
313        }
314        long startNanos = System.nanoTime();
315        long timeoutNanos = unit.toNanos(time);
316        long remainingNanos = timeoutNanos;
317        boolean interruptIgnored = false;
318        try {
319          while (true) {
320            try {
321              return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
322            } catch (InterruptedException ignored) {
323              interruptIgnored = true;
324              remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
325            }
326          }
327        } finally {
328          if (interruptIgnored) {
329            Thread.currentThread().interrupt();
330          }
331        }
332      }
333    
334      /**
335       * Enters this monitor. Blocks at most the given time, and may be interrupted.
336       *
337       * @return whether the monitor was entered
338       */
339      public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
340        return lock.tryLock(time, unit);
341      }
342    
343      /**
344       * Enters this monitor if it is possible to do so immediately. Does not block.
345       *
346       * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
347       *
348       * @return whether the monitor was entered
349       */
350      public boolean tryEnter() {
351        return lock.tryLock();
352      }
353    
354      /**
355       * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
356       */
357      public void enterWhen(Guard guard) throws InterruptedException {
358        if (guard.monitor != this) {
359          throw new IllegalMonitorStateException();
360        }
361        final ReentrantLock lock = this.lock;
362        boolean reentrant = lock.isHeldByCurrentThread();
363        boolean success = false;
364        lock.lockInterruptibly();
365        try {
366          waitInterruptibly(guard, reentrant);
367          success = true;
368        } finally {
369          if (!success) {
370            lock.unlock();
371          }
372        }
373      }
374    
375      /**
376       * Enters this monitor when the guard is satisfied. Blocks indefinitely.
377       */
378      public void enterWhenUninterruptibly(Guard guard) {
379        if (guard.monitor != this) {
380          throw new IllegalMonitorStateException();
381        }
382        final ReentrantLock lock = this.lock;
383        boolean reentrant = lock.isHeldByCurrentThread();
384        boolean success = false;
385        lock.lock();
386        try {
387          waitUninterruptibly(guard, reentrant);
388          success = true;
389        } finally {
390          if (!success) {
391            lock.unlock();
392          }
393        }
394      }
395    
396      /**
397       * Enters this monitor when the guard is satisfied. Blocks at most the given time, including both
398       * the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
399       * interrupted.
400       *
401       * @return whether the monitor was entered
402       */
403      public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
404        if (guard.monitor != this) {
405          throw new IllegalMonitorStateException();
406        }
407        final ReentrantLock lock = this.lock;
408        boolean reentrant = lock.isHeldByCurrentThread();
409        long remainingNanos;
410        if (!fair && lock.tryLock()) {
411          remainingNanos = unit.toNanos(time);
412        } else {
413          long startNanos = System.nanoTime();
414          if (!lock.tryLock(time, unit)) {
415            return false;
416          }
417          remainingNanos = unit.toNanos(time) - (System.nanoTime() - startNanos);
418        }
419        boolean satisfied = false;
420        try {
421          satisfied = waitInterruptibly(guard, remainingNanos, reentrant);
422        } finally {
423          if (!satisfied) {
424            lock.unlock();
425          }
426        }
427        return satisfied;
428      }
429    
430      /**
431       * Enters this monitor when the guard is satisfied. Blocks at most the given time, including
432       * both the time to acquire the lock and the time to wait for the guard to be satisfied.
433       *
434       * @return whether the monitor was entered
435       */
436      public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
437        if (guard.monitor != this) {
438          throw new IllegalMonitorStateException();
439        }
440        final ReentrantLock lock = this.lock;
441        boolean reentrant = lock.isHeldByCurrentThread();
442        boolean interruptIgnored = false;
443        try {
444          long remainingNanos;
445          if (!fair && lock.tryLock()) {
446            remainingNanos = unit.toNanos(time);
447          } else {
448            long startNanos = System.nanoTime();
449            long timeoutNanos = unit.toNanos(time);
450            remainingNanos = timeoutNanos;
451            while (true) {
452              try {
453                if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
454                  break;
455                } else {
456                  return false;
457                }
458              } catch (InterruptedException ignored) {
459                interruptIgnored = true;
460              } finally {
461                remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
462              }
463            }
464          }
465          boolean satisfied = false;
466          try {
467            satisfied = waitUninterruptibly(guard, remainingNanos, reentrant);
468          } finally {
469            if (!satisfied) {
470              lock.unlock();
471            }
472          }
473          return satisfied;
474        } finally {
475          if (interruptIgnored) {
476            Thread.currentThread().interrupt();
477          }
478        }
479      }
480    
481      /**
482       * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
483       * does not wait for the guard to be satisfied.
484       *
485       * @return whether the monitor was entered
486       */
487      public boolean enterIf(Guard guard) {
488        if (guard.monitor != this) {
489          throw new IllegalMonitorStateException();
490        }
491        final ReentrantLock lock = this.lock;
492        lock.lock();
493        boolean satisfied = false;
494        try {
495          satisfied = guard.isSatisfied();
496        } finally {
497          if (!satisfied) {
498            lock.unlock();
499          }
500        }
501        return satisfied;
502      }
503    
504      /**
505       * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
506       * not wait for the guard to be satisfied, and may be interrupted.
507       *
508       * @return whether the monitor was entered
509       */
510      public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
511        if (guard.monitor != this) {
512          throw new IllegalMonitorStateException();
513        }
514        final ReentrantLock lock = this.lock;
515        lock.lockInterruptibly();
516        boolean satisfied = false;
517        try {
518          satisfied = guard.isSatisfied();
519        } finally {
520          if (!satisfied) {
521            lock.unlock();
522          }
523        }
524        return satisfied;
525      }
526    
527      /**
528       * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
529       * lock, but does not wait for the guard to be satisfied.
530       *
531       * @return whether the monitor was entered
532       */
533      public boolean enterIf(Guard guard, long time, TimeUnit unit) {
534        if (guard.monitor != this) {
535          throw new IllegalMonitorStateException();
536        }
537        final ReentrantLock lock = this.lock;
538        if (!enter(time, unit)) {
539          return false;
540        }
541        boolean satisfied = false;
542        try {
543          satisfied = guard.isSatisfied();
544        } finally {
545          if (!satisfied) {
546            lock.unlock();
547          }
548        }
549        return satisfied;
550      }
551    
552      /**
553       * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
554       * lock, but does not wait for the guard to be satisfied, and may be interrupted.
555       *
556       * @return whether the monitor was entered
557       */
558      public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
559          throws InterruptedException {
560        if (guard.monitor != this) {
561          throw new IllegalMonitorStateException();
562        }
563        final ReentrantLock lock = this.lock;
564        if (!lock.tryLock(time, unit)) {
565          return false;
566        }
567        boolean satisfied = false;
568        try {
569          satisfied = guard.isSatisfied();
570        } finally {
571          if (!satisfied) {
572            lock.unlock();
573          }
574        }
575        return satisfied;
576      }
577    
578      /**
579       * Enters this monitor if it is possible to do so immediately and the guard is satisfied. Does not
580       * block acquiring the lock and does not wait for the guard to be satisfied.
581       *
582       * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
583       *
584       * @return whether the monitor was entered
585       */
586      public boolean tryEnterIf(Guard guard) {
587        if (guard.monitor != this) {
588          throw new IllegalMonitorStateException();
589        }
590        final ReentrantLock lock = this.lock;
591        if (!lock.tryLock()) {
592          return false;
593        }
594        boolean satisfied = false;
595        try {
596          satisfied = guard.isSatisfied();
597        } finally {
598          if (!satisfied) {
599            lock.unlock();
600          }
601        }
602        return satisfied;
603      }
604    
605      /**
606       * Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
607       * called only by a thread currently occupying this monitor.
608       */
609      public void waitFor(Guard guard) throws InterruptedException {
610        if (guard.monitor != this) {
611          throw new IllegalMonitorStateException();
612        }
613        if (!lock.isHeldByCurrentThread()) {
614          throw new IllegalMonitorStateException();
615        }
616        waitInterruptibly(guard, true);
617      }
618    
619      /**
620       * Waits for the guard to be satisfied. Waits indefinitely. May be called only by a thread
621       * currently occupying this monitor.
622       */
623      public void waitForUninterruptibly(Guard guard) {
624        if (guard.monitor != this) {
625          throw new IllegalMonitorStateException();
626        }
627        if (!lock.isHeldByCurrentThread()) {
628          throw new IllegalMonitorStateException();
629        }
630        waitUninterruptibly(guard, true);
631      }
632    
633      /**
634       * Waits for the guard to be satisfied. Waits at most the given time, and may be interrupted.
635       * May be called only by a thread currently occupying this monitor.
636       *
637       * @return whether the guard is now satisfied
638       */
639      public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
640        if (guard.monitor != this) {
641          throw new IllegalMonitorStateException();
642        }
643        if (!lock.isHeldByCurrentThread()) {
644          throw new IllegalMonitorStateException();
645        }
646        return waitInterruptibly(guard, unit.toNanos(time), true);
647      }
648    
649      /**
650       * Waits for the guard to be satisfied. Waits at most the given time. May be called only by a
651       * thread currently occupying this monitor.
652       *
653       * @return whether the guard is now satisfied
654       */
655      public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
656        if (guard.monitor != this) {
657          throw new IllegalMonitorStateException();
658        }
659        if (!lock.isHeldByCurrentThread()) {
660          throw new IllegalMonitorStateException();
661        }
662        return waitUninterruptibly(guard, unit.toNanos(time), true);
663      }
664    
665      /**
666       * Leaves this monitor. May be called only by a thread currently occupying this monitor.
667       */
668      public void leave() {
669        final ReentrantLock lock = this.lock;
670        if (!lock.isHeldByCurrentThread()) {
671          throw new IllegalMonitorStateException();
672        }
673        try {
674          signalConditionsOfSatisfiedGuards(null);
675        } finally {
676          lock.unlock();
677        }
678      }
679    
680      /**
681       * Returns whether this monitor is using a fair ordering policy.
682       */
683      public boolean isFair() {
684        return lock.isFair();
685      }
686    
687      /**
688       * Returns whether this monitor is occupied by any thread. This method is designed for use in
689       * monitoring of the system state, not for synchronization control.
690       */
691      public boolean isOccupied() {
692        return lock.isLocked();
693      }
694    
695      /**
696       * Returns whether the current thread is occupying this monitor (has entered more times than it
697       * has left).
698       */
699      public boolean isOccupiedByCurrentThread() {
700        return lock.isHeldByCurrentThread();
701      }
702    
703      /**
704       * Returns the number of times the current thread has entered this monitor in excess of the number
705       * of times it has left. Returns 0 if the current thread is not occupying this monitor.
706       */
707      public int getOccupiedDepth() {
708        return lock.getHoldCount();
709      }
710    
711      /**
712       * Returns an estimate of the number of threads waiting to enter this monitor. The value is only
713       * an estimate because the number of threads may change dynamically while this method traverses
714       * internal data structures. This method is designed for use in monitoring of the system state,
715       * not for synchronization control.
716       */
717      public int getQueueLength() {
718        return lock.getQueueLength();
719      }
720    
721      /**
722       * Returns whether any threads are waiting to enter this monitor. Note that because cancellations
723       * may occur at any time, a {@code true} return does not guarantee that any other thread will ever
724       * enter this monitor. This method is designed primarily for use in monitoring of the system
725       * state.
726       */
727      public boolean hasQueuedThreads() {
728        return lock.hasQueuedThreads();
729      }
730    
731      /**
732       * Queries whether the given thread is waiting to enter this monitor. Note that because
733       * cancellations may occur at any time, a {@code true} return does not guarantee that this thread
734       * will ever enter this monitor. This method is designed primarily for use in monitoring of the
735       * system state.
736       */
737      public boolean hasQueuedThread(Thread thread) {
738        return lock.hasQueuedThread(thread);
739      }
740    
741      /**
742       * Queries whether any threads are waiting for the given guard to become satisfied. Note that
743       * because timeouts and interrupts may occur at any time, a {@code true} return does not guarantee
744       * that the guard becoming satisfied in the future will awaken any threads. This method is
745       * designed primarily for use in monitoring of the system state.
746       */
747      public boolean hasWaiters(Guard guard) {
748        if (guard.monitor != this) {
749          throw new IllegalMonitorStateException();
750        }
751        lock.lock();
752        try {
753          return guard.waiterCount > 0;
754        } finally {
755          lock.unlock();
756        }
757      }
758    
759      /**
760       * Returns an estimate of the number of threads waiting for the given guard to become satisfied.
761       * Note that because timeouts and interrupts may occur at any time, the estimate serves only as an
762       * upper bound on the actual number of waiters. This method is designed for use in monitoring of
763       * the system state, not for synchronization control.
764       */
765      public int getWaitQueueLength(Guard guard) {
766        if (guard.monitor != this) {
767          throw new IllegalMonitorStateException();
768        }
769        lock.lock();
770        try {
771          return guard.waiterCount;
772        } finally {
773          lock.unlock();
774        }
775      }
776    
777      @GuardedBy("lock")
778      private void signalConditionsOfSatisfiedGuards(@Nullable Guard interruptedGuard) {
779        final ArrayList<Guard> guards = this.activeGuards;
780        final int guardCount = guards.size();
781        try {
782          for (int i = 0; i < guardCount; i++) {
783            Guard guard = guards.get(i);
784            if ((guard == interruptedGuard) && (guard.waiterCount == 1)) {
785              // That one waiter was just interrupted and is throwing InterruptedException rather than
786              // paying attention to the guard being satisfied, so find another waiter on another guard.
787              continue;
788            }
789            if (guard.isSatisfied()) {
790              guard.condition.signal();
791              return;
792            }
793          }
794        } catch (Throwable throwable) {
795          for (int i = 0; i < guardCount; i++) {
796            Guard guard = guards.get(i);
797            guard.condition.signalAll();
798          }
799          throw Throwables.propagate(throwable);
800        }
801      }
802      
803      @GuardedBy("lock")
804      private void incrementWaiters(Guard guard) {
805        int waiters = guard.waiterCount++;
806        if (waiters == 0) {
807          activeGuards.add(guard);
808        }
809      }
810    
811      @GuardedBy("lock")
812      private void decrementWaiters(Guard guard) {
813        int waiters = --guard.waiterCount;
814        if (waiters == 0) {
815          activeGuards.remove(guard);
816        }
817      }
818    
819      @GuardedBy("lock")
820      private void waitInterruptibly(Guard guard, boolean signalBeforeWaiting)
821          throws InterruptedException {
822        if (!guard.isSatisfied()) {
823          if (signalBeforeWaiting) {
824            signalConditionsOfSatisfiedGuards(null);
825          }
826          incrementWaiters(guard);
827          try {
828            final Condition condition = guard.condition;
829            do {
830              try {
831                condition.await();
832              } catch (InterruptedException interrupt) {
833                try {
834                  signalConditionsOfSatisfiedGuards(guard);
835                } catch (Throwable throwable) {
836                  Thread.currentThread().interrupt();
837                  throw Throwables.propagate(throwable);
838                }
839                throw interrupt;
840              }
841            } while (!guard.isSatisfied());
842          } finally {
843            decrementWaiters(guard);
844          }
845        }
846      }
847    
848      @GuardedBy("lock")
849      private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
850        if (!guard.isSatisfied()) {
851          if (signalBeforeWaiting) {
852            signalConditionsOfSatisfiedGuards(null);
853          }
854          incrementWaiters(guard);
855          try {
856            final Condition condition = guard.condition;
857            do {
858              condition.awaitUninterruptibly();
859            } while (!guard.isSatisfied());
860          } finally {
861            decrementWaiters(guard);
862          }
863        }
864      }
865    
866      @GuardedBy("lock")
867      private boolean waitInterruptibly(Guard guard, long remainingNanos, boolean signalBeforeWaiting)
868          throws InterruptedException {
869        if (!guard.isSatisfied()) {
870          if (signalBeforeWaiting) {
871            signalConditionsOfSatisfiedGuards(null);
872          }
873          incrementWaiters(guard);
874          try {
875            final Condition condition = guard.condition;
876            do {
877              if (remainingNanos <= 0) {
878                return false;
879              }
880              try {
881                remainingNanos = condition.awaitNanos(remainingNanos);
882              } catch (InterruptedException interrupt) {
883                try {
884                  signalConditionsOfSatisfiedGuards(guard);
885                } catch (Throwable throwable) {
886                  Thread.currentThread().interrupt();
887                  throw Throwables.propagate(throwable);
888                }
889                throw interrupt;
890              }
891            } while (!guard.isSatisfied());
892          } finally {
893            decrementWaiters(guard);
894          }
895        }
896        return true;
897      }
898    
899      @GuardedBy("lock")
900      private boolean waitUninterruptibly(Guard guard, long timeoutNanos,
901          boolean signalBeforeWaiting) {
902        if (!guard.isSatisfied()) {
903          long startNanos = System.nanoTime();
904          if (signalBeforeWaiting) {
905            signalConditionsOfSatisfiedGuards(null);
906          }
907          boolean interruptIgnored = false;
908          try {
909            incrementWaiters(guard);
910            try {
911              final Condition condition = guard.condition;
912              long remainingNanos = timeoutNanos;
913              do {
914                if (remainingNanos <= 0) {
915                  return false;
916                }
917                try {
918                  remainingNanos = condition.awaitNanos(remainingNanos);
919                } catch (InterruptedException ignored) {
920                  try {
921                    signalConditionsOfSatisfiedGuards(guard);
922                  } catch (Throwable throwable) {
923                    Thread.currentThread().interrupt();
924                    throw Throwables.propagate(throwable);
925                  }
926                  interruptIgnored = true;
927                  remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
928                }
929              } while (!guard.isSatisfied());
930            } finally {
931              decrementWaiters(guard);
932            }
933          } finally {
934            if (interruptIgnored) {
935              Thread.currentThread().interrupt();
936            }
937          }
938        }
939        return true;
940      }
941    
942    }