1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 /** 20 * Class that implements the condition variable locking paradigm. 21 * 22 * <p> 23 * This differs from the built-in java.lang.Object wait() and notify() 24 * in that this class contains the condition to wait on itself. That means 25 * open(), close() and block() are sticky. If open() is called before block(), 26 * block() will not block, and instead return immediately. 27 * 28 * <p> 29 * This class uses itself as the object to wait on, so if you wait() 30 * or notify() on a ConditionVariable, the results are undefined. 31 */ 32 public class ConditionVariable 33 { 34 private volatile boolean mCondition; 35 36 /** 37 * Create the ConditionVariable in the default closed state. 38 */ ConditionVariable()39 public ConditionVariable() 40 { 41 mCondition = false; 42 } 43 44 /** 45 * Create the ConditionVariable with the given state. 46 * 47 * <p> 48 * Pass true for opened and false for closed. 49 */ ConditionVariable(boolean state)50 public ConditionVariable(boolean state) 51 { 52 mCondition = state; 53 } 54 55 /** 56 * Open the condition, and release all threads that are blocked. 57 * 58 * <p> 59 * Any threads that later approach block() will not block unless close() 60 * is called. 61 */ open()62 public void open() 63 { 64 synchronized (this) { 65 boolean old = mCondition; 66 mCondition = true; 67 if (!old) { 68 this.notifyAll(); 69 } 70 } 71 } 72 73 /** 74 * Reset the condition to the closed state. 75 * 76 * <p> 77 * Any threads that call block() will block until someone calls open. 78 */ close()79 public void close() 80 { 81 synchronized (this) { 82 mCondition = false; 83 } 84 } 85 86 /** 87 * Block the current thread until the condition is opened. 88 * 89 * <p> 90 * If the condition is already opened, return immediately. 91 */ block()92 public void block() 93 { 94 synchronized (this) { 95 while (!mCondition) { 96 try { 97 this.wait(); 98 } 99 catch (InterruptedException e) { 100 } 101 } 102 } 103 } 104 105 /** 106 * Block the current thread until the condition is opened or until 107 * timeoutMs milliseconds have passed. 108 * 109 * <p> 110 * If the condition is already opened, return immediately. 111 * 112 * @param timeoutMs the maximum time to wait in milliseconds. 113 * 114 * @return true if the condition was opened, false if the call returns 115 * because of the timeout. 116 */ block(long timeoutMs)117 public boolean block(long timeoutMs) 118 { 119 // Object.wait(0) means wait forever, to mimic this, we just 120 // call the other block() method in that case. It simplifies 121 // this code for the common case. 122 if (timeoutMs != 0) { 123 synchronized (this) { 124 long now = SystemClock.elapsedRealtime(); 125 long end = now + timeoutMs; 126 while (!mCondition && now < end) { 127 try { 128 this.wait(end-now); 129 } 130 catch (InterruptedException e) { 131 } 132 now = SystemClock.elapsedRealtime(); 133 } 134 return mCondition; 135 } 136 } else { 137 this.block(); 138 return true; 139 } 140 } 141 } 142