11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2010 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Throwables;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Lists;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ArrayList;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.locks.Condition;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.locks.ReentrantLock;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.concurrent.GuardedBy;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A synchronization abstraction supporting waiting on arbitrary boolean conditions.
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class is intended as a replacement for {@link ReentrantLock}. Code using {@code Monitor}
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is less error-prone and more readable than code using {@code ReentrantLock}, without significant
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * performance loss. {@code Monitor} even has the potential for performance gain by optimizing the
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * evaluation and signaling of conditions.  Signaling is entirely
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <a href="http://en.wikipedia.org/wiki/Monitor_(synchronization)#Implicit_signaling">
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * implicit</a>.
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * By eliminating explicit signaling, this class can guarantee that only one thread is awakened
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * when a condition becomes true (no "signaling storms" due to use of {@link
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * java.util.concurrent.locks.Condition#signalAll Condition.signalAll}) and that no signals are lost
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * (no "hangs" due to incorrect use of {@link java.util.concurrent.locks.Condition#signal
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Condition.signal}).
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>A thread is said to <i>occupy</i> a monitor if it has <i>entered</i> the monitor but not yet
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <i>left</i>. Only one thread may occupy a given monitor at any moment. A monitor is also
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * reentrant, so a thread may enter a monitor any number of times, and then must leave the same
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * number of times. The <i>enter</i> and <i>leave</i> operations have the same synchronization
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * semantics as the built-in Java language synchronization primitives.
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>A call to any of the <i>enter</i> methods with <b>void</b> return type should always be
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * followed immediately by a <i>try/finally</i> block to ensure that the current thread leaves the
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * monitor cleanly: <pre>   {@code
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   monitor.enter();
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   try {
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     // do things while occupying the monitor
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   } finally {
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     monitor.leave();
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   }}</pre>
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A call to any of the <i>enter</i> methods with <b>boolean</b> return type should always appear as
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the condition of an <i>if</i> statement containing a <i>try/finally</i> block to ensure that the
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * current thread leaves the monitor cleanly: <pre>   {@code
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   if (monitor.tryEnter()) {
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     try {
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       // do things while occupying the monitor
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     } finally {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       monitor.leave();
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   } else {
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     // do other things since the monitor was not available
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   }}</pre>
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h2>Comparison with {@code synchronized} and {@code ReentrantLock}</h2>
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The following examples show a simple threadsafe holder expressed using {@code synchronized},
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ReentrantLock}, and {@code Monitor}.
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h3>{@code synchronized}</h3>
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This version is the fewest lines of code, largely because the synchronization mechanism used
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is built into the language and runtime. But the programmer has to remember to avoid a couple of
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * common bugs: The {@code wait()} must be inside a {@code while} instead of an {@code if}, and
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code notifyAll()} must be used instead of {@code notify()} because there are two different
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * logical conditions being awaited. <pre>   {@code
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   public class SafeBox<V> {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private V value;
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public synchronized V get() throws InterruptedException {
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       while (value == null) {
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         wait();
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       V result = value;
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       value = null;
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       notifyAll();
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       return result;
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public synchronized void set(V newValue) throws InterruptedException {
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       while (value != null) {
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         wait();
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       value = newValue;
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       notifyAll();
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   }}</pre>
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h3>{@code ReentrantLock}</h3>
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This version is much more verbose than the {@code synchronized} version, and still suffers
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * from the need for the programmer to remember to use {@code while} instead of {@code if}.
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * However, one advantage is that we can introduce two separate {@code Condition} objects, which
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * allows us to use {@code signal()} instead of {@code signalAll()}, which may be a performance
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * benefit. <pre>   {@code
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   public class SafeBox<V> {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final ReentrantLock lock = new ReentrantLock();
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final Condition valuePresent = lock.newCondition();
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final Condition valueAbsent = lock.newCondition();
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private V value;
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public V get() throws InterruptedException {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       lock.lock();
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       try {
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         while (value == null) {
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *           valuePresent.await();
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         }
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         V result = value;
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         value = null;
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         valueAbsent.signal();
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         return result;
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       } finally {
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         lock.unlock();
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public void set(V newValue) throws InterruptedException {
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       lock.lock();
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       try {
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         while (value != null) {
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *           valueAbsent.await();
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         value = newValue;
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         valuePresent.signal();
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       } finally {
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         lock.unlock();
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   }}</pre>
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h3>{@code Monitor}</h3>
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This version adds some verbosity around the {@code Guard} objects, but removes that same
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * verbosity, and more, from the {@code get} and {@code set} methods. {@code Monitor} implements the
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * same efficient signaling as we had to hand-code in the {@code ReentrantLock} version above.
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Finally, the programmer no longer has to hand-code the wait loop, and therefore doesn't have to
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * remember to use {@code while} instead of {@code if}. <pre>   {@code
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   public class SafeBox<V> {
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final Monitor monitor = new Monitor();
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       public boolean isSatisfied() {
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         return value != null;
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     };
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) {
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       public boolean isSatisfied() {
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         return value == null;
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     };
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     private V value;
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public V get() throws InterruptedException {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       monitor.enterWhen(valuePresent);
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       try {
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         V result = value;
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         value = null;
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         return result;
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       } finally {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         monitor.leave();
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     public void set(V newValue) throws InterruptedException {
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       monitor.enterWhen(valueAbsent);
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       try {
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         value = newValue;
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       } finally {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *         monitor.leave();
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *       }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     }
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *   }}</pre>
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Justin T. Sampson
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class Monitor {
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // TODO: Use raw LockSupport or AbstractQueuedSynchronizer instead of ReentrantLock.
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A boolean condition for which a thread may wait. A {@code Guard} is associated with a single
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code Monitor}. The monitor may check the guard at arbitrary times from any thread occupying
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the monitor, so code should not be written to rely on how often a guard might or might not be
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * checked.
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>If a {@code Guard} is passed into any method of a {@code Monitor} other than the one it is
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * associated with, an {@link IllegalMonitorStateException} is thrown.
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @since 10.0
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Beta
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public abstract static class Guard {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Monitor monitor;
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Condition condition;
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("monitor.lock")
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int waiterCount = 0;
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    protected Guard(Monitor monitor) {
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.monitor = checkNotNull(monitor, "monitor");
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.condition = monitor.lock.newCondition();
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Evaluates this guard's boolean condition. This method is always called with the associated
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * monitor already occupied. Implementations of this method must depend only on state protected
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * by the associated monitor, and must not modify that state.
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public abstract boolean isSatisfied();
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public final boolean equals(Object other) {
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Overridden as final to ensure identity semantics in Monitor.activeGuards.
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this == other;
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public final int hashCode() {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Overridden as final to ensure identity semantics in Monitor.activeGuards.
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return super.hashCode();
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Whether this monitor is fair.
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final boolean fair;
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The lock underlying this monitor.
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ReentrantLock lock;
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The guards associated with this monitor that currently have waiters ({@code waiterCount > 0}).
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This is an ArrayList rather than, say, a HashSet so that iteration and almost all adds don't
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * incur any object allocation overhead.
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ArrayList<Guard> activeGuards = Lists.newArrayListWithCapacity(1);
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a monitor with a non-fair (but fast) ordering policy. Equivalent to {@code
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Monitor(false)}.
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Monitor() {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this(false);
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a monitor with the given ordering policy.
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param fair whether this monitor should use a fair ordering policy rather than a non-fair (but
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *        fast) one
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Monitor(boolean fair) {
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.fair = fair;
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.lock = new ReentrantLock(fair);
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor. Blocks indefinitely.
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void enter() {
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lock();
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor. Blocks indefinitely, but may be interrupted.
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void enterInterruptibly() throws InterruptedException {
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lockInterruptibly();
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor. Blocks at most the given time.
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enter(long time, TimeUnit unit) {
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!fair && lock.tryLock()) {
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long startNanos = System.nanoTime();
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long timeoutNanos = unit.toNanos(time);
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long remainingNanos = timeoutNanos;
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean interruptIgnored = false;
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (true) {
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (InterruptedException ignored) {
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          interruptIgnored = true;
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (interruptIgnored) {
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Thread.currentThread().interrupt();
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor. Blocks at most the given time, and may be interrupted.
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.tryLock(time, unit);
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if it is possible to do so immediately. Does not block.
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean tryEnter() {
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.tryLock();
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void enterWhen(Guard guard) throws InterruptedException {
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reentrant = lock.isHeldByCurrentThread();
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean success = false;
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lockInterruptibly();
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      waitInterruptibly(guard, reentrant);
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      success = true;
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!success) {
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor when the guard is satisfied. Blocks indefinitely.
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void enterWhenUninterruptibly(Guard guard) {
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reentrant = lock.isHeldByCurrentThread();
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean success = false;
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lock();
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      waitUninterruptibly(guard, reentrant);
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      success = true;
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!success) {
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor when the guard is satisfied. Blocks at most the given time, including both
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * interrupted.
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reentrant = lock.isHeldByCurrentThread();
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long remainingNanos;
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!fair && lock.tryLock()) {
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      remainingNanos = unit.toNanos(time);
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long startNanos = System.nanoTime();
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!lock.tryLock(time, unit)) {
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      remainingNanos = unit.toNanos(time) - (System.nanoTime() - startNanos);
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = waitInterruptibly(guard, remainingNanos, reentrant);
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor when the guard is satisfied. Blocks at most the given time, including
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * both the time to acquire the lock and the time to wait for the guard to be satisfied.
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reentrant = lock.isHeldByCurrentThread();
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean interruptIgnored = false;
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long remainingNanos;
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!fair && lock.tryLock()) {
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        remainingNanos = unit.toNanos(time);
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long startNanos = System.nanoTime();
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long timeoutNanos = unit.toNanos(time);
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        remainingNanos = timeoutNanos;
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        while (true) {
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          try {
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              break;
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return false;
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } catch (InterruptedException ignored) {
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            interruptIgnored = true;
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } finally {
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean satisfied = false;
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        satisfied = waitUninterruptibly(guard, remainingNanos, reentrant);
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (!satisfied) {
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          lock.unlock();
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return satisfied;
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (interruptIgnored) {
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Thread.currentThread().interrupt();
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * does not wait for the guard to be satisfied.
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterIf(Guard guard) {
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lock();
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = guard.isSatisfied();
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * not wait for the guard to be satisfied, and may be interrupted.
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lockInterruptibly();
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = guard.isSatisfied();
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * lock, but does not wait for the guard to be satisfied.
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterIf(Guard guard, long time, TimeUnit unit) {
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!enter(time, unit)) {
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = guard.isSatisfied();
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * lock, but does not wait for the guard to be satisfied, and may be interrupted.
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws InterruptedException {
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.tryLock(time, unit)) {
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = guard.isSatisfied();
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Enters this monitor if it is possible to do so immediately and the guard is satisfied. Does not
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * block acquiring the lock and does not wait for the guard to be satisfied.
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the monitor was entered
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean tryEnterIf(Guard guard) {
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.tryLock()) {
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean satisfied = false;
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      satisfied = guard.isSatisfied();
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!satisfied) {
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock.unlock();
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return satisfied;
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * called only by a thread currently occupying this monitor.
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void waitFor(Guard guard) throws InterruptedException {
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.isHeldByCurrentThread()) {
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    waitInterruptibly(guard, true);
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Waits for the guard to be satisfied. Waits indefinitely. May be called only by a thread
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * currently occupying this monitor.
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void waitForUninterruptibly(Guard guard) {
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.isHeldByCurrentThread()) {
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    waitUninterruptibly(guard, true);
6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Waits for the guard to be satisfied. Waits at most the given time, and may be interrupted.
6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * May be called only by a thread currently occupying this monitor.
6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the guard is now satisfied
6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.isHeldByCurrentThread()) {
6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return waitInterruptibly(guard, unit.toNanos(time), true);
6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Waits for the guard to be satisfied. Waits at most the given time. May be called only by a
6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * thread currently occupying this monitor.
6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return whether the guard is now satisfied
6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.isHeldByCurrentThread()) {
6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return waitUninterruptibly(guard, unit.toNanos(time), true);
6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Leaves this monitor. May be called only by a thread currently occupying this monitor.
6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void leave() {
6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReentrantLock lock = this.lock;
6701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!lock.isHeldByCurrentThread()) {
6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      signalConditionsOfSatisfiedGuards(null);
6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock.unlock();
6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns whether this monitor is using a fair ordering policy.
6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean isFair() {
6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.isFair();
6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns whether this monitor is occupied by any thread. This method is designed for use in
6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * monitoring of the system state, not for synchronization control.
6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean isOccupied() {
6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.isLocked();
6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns whether the current thread is occupying this monitor (has entered more times than it
6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * has left).
6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean isOccupiedByCurrentThread() {
7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.isHeldByCurrentThread();
7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the number of times the current thread has entered this monitor in excess of the number
7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of times it has left. Returns 0 if the current thread is not occupying this monitor.
7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int getOccupiedDepth() {
7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.getHoldCount();
7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an estimate of the number of threads waiting to enter this monitor. The value is only
7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * an estimate because the number of threads may change dynamically while this method traverses
7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * internal data structures. This method is designed for use in monitoring of the system state,
7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * not for synchronization control.
7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int getQueueLength() {
7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.getQueueLength();
7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns whether any threads are waiting to enter this monitor. Note that because cancellations
7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * may occur at any time, a {@code true} return does not guarantee that any other thread will ever
7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * enter this monitor. This method is designed primarily for use in monitoring of the system
7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * state.
7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean hasQueuedThreads() {
7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.hasQueuedThreads();
7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Queries whether the given thread is waiting to enter this monitor. Note that because
7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * cancellations may occur at any time, a {@code true} return does not guarantee that this thread
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * will ever enter this monitor. This method is designed primarily for use in monitoring of the
7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * system state.
7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean hasQueuedThread(Thread thread) {
7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return lock.hasQueuedThread(thread);
7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Queries whether any threads are waiting for the given guard to become satisfied. Note that
7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * because timeouts and interrupts may occur at any time, a {@code true} return does not guarantee
7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * that the guard becoming satisfied in the future will awaken any threads. This method is
7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * designed primarily for use in monitoring of the system state.
7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean hasWaiters(Guard guard) {
7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lock();
7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return guard.waiterCount > 0;
7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock.unlock();
7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an estimate of the number of threads waiting for the given guard to become satisfied.
7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Note that because timeouts and interrupts may occur at any time, the estimate serves only as an
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * upper bound on the actual number of waiters. This method is designed for use in monitoring of
7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the system state, not for synchronization control.
7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int getWaitQueueLength(Guard guard) {
7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (guard.monitor != this) {
7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalMonitorStateException();
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    lock.lock();
7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return guard.waiterCount;
7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock.unlock();
7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void signalConditionsOfSatisfiedGuards(@Nullable Guard interruptedGuard) {
7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ArrayList<Guard> guards = this.activeGuards;
7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int guardCount = guards.size();
7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < guardCount; i++) {
7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Guard guard = guards.get(i);
7841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if ((guard == interruptedGuard) && (guard.waiterCount == 1)) {
7851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // That one waiter was just interrupted and is throwing InterruptedException rather than
7861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // paying attention to the guard being satisfied, so find another waiter on another guard.
7871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue;
7881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
7891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (guard.isSatisfied()) {
7901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          guard.condition.signal();
7911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return;
7921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
7931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
7941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (Throwable throwable) {
7951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < guardCount; i++) {
7961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Guard guard = guards.get(i);
7971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        guard.condition.signalAll();
7981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
7991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw Throwables.propagate(throwable);
8001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
8041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void incrementWaiters(Guard guard) {
8051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int waiters = guard.waiterCount++;
8061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (waiters == 0) {
8071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      activeGuards.add(guard);
8081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
8121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void decrementWaiters(Guard guard) {
8131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int waiters = --guard.waiterCount;
8141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (waiters == 0) {
8151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      activeGuards.remove(guard);
8161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
8201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void waitInterruptibly(Guard guard, boolean signalBeforeWaiting)
8211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws InterruptedException {
8221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!guard.isSatisfied()) {
8231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (signalBeforeWaiting) {
8241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        signalConditionsOfSatisfiedGuards(null);
8251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      incrementWaiters(guard);
8271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
8281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        final Condition condition = guard.condition;
8291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        do {
8301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          try {
8311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            condition.await();
8321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } catch (InterruptedException interrupt) {
8331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              signalConditionsOfSatisfiedGuards(guard);
8351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } catch (Throwable throwable) {
8361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              Thread.currentThread().interrupt();
8371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw Throwables.propagate(throwable);
8381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
8391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            throw interrupt;
8401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
8411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } while (!guard.isSatisfied());
8421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
8431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        decrementWaiters(guard);
8441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
8491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
8501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!guard.isSatisfied()) {
8511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (signalBeforeWaiting) {
8521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        signalConditionsOfSatisfiedGuards(null);
8531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      incrementWaiters(guard);
8551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
8561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        final Condition condition = guard.condition;
8571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        do {
8581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          condition.awaitUninterruptibly();
8591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } while (!guard.isSatisfied());
8601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
8611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        decrementWaiters(guard);
8621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private boolean waitInterruptibly(Guard guard, long remainingNanos, boolean signalBeforeWaiting)
8681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws InterruptedException {
8691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!guard.isSatisfied()) {
8701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (signalBeforeWaiting) {
8711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        signalConditionsOfSatisfiedGuards(null);
8721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      incrementWaiters(guard);
8741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
8751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        final Condition condition = guard.condition;
8761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        do {
8771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (remainingNanos <= 0) {
8781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return false;
8791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
8801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          try {
8811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            remainingNanos = condition.awaitNanos(remainingNanos);
8821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } catch (InterruptedException interrupt) {
8831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
8841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              signalConditionsOfSatisfiedGuards(guard);
8851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } catch (Throwable throwable) {
8861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              Thread.currentThread().interrupt();
8871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw Throwables.propagate(throwable);
8881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
8891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            throw interrupt;
8901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
8911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } while (!guard.isSatisfied());
8921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
8931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        decrementWaiters(guard);
8941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
8951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return true;
8971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("lock")
9001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private boolean waitUninterruptibly(Guard guard, long timeoutNanos,
9011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean signalBeforeWaiting) {
9021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!guard.isSatisfied()) {
9031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long startNanos = System.nanoTime();
9041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (signalBeforeWaiting) {
9051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        signalConditionsOfSatisfiedGuards(null);
9061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
9071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean interruptIgnored = false;
9081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
9091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        incrementWaiters(guard);
9101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
9111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          final Condition condition = guard.condition;
9121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          long remainingNanos = timeoutNanos;
9131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          do {
9141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (remainingNanos <= 0) {
9151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return false;
9161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
9171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
9181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              remainingNanos = condition.awaitNanos(remainingNanos);
9191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } catch (InterruptedException ignored) {
9201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              try {
9211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                signalConditionsOfSatisfiedGuards(guard);
9221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } catch (Throwable throwable) {
9231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                Thread.currentThread().interrupt();
9241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                throw Throwables.propagate(throwable);
9251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
9261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              interruptIgnored = true;
9271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
9281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
9291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } while (!guard.isSatisfied());
9301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
9311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          decrementWaiters(guard);
9321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
9331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
9341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (interruptIgnored) {
9351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Thread.currentThread().interrupt();
9361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
9371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
9381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return true;
9401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
9411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
943