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 @android.ravenwood.annotation.RavenwoodKeepWholeClass 33 public class ConditionVariable 34 { 35 private volatile boolean mCondition; 36 37 /** 38 * Create the ConditionVariable in the default closed state. 39 */ ConditionVariable()40 public ConditionVariable() 41 { 42 mCondition = false; 43 } 44 45 /** 46 * Create the ConditionVariable with the given state. 47 * 48 * <p> 49 * Pass true for opened and false for closed. 50 */ ConditionVariable(boolean state)51 public ConditionVariable(boolean state) 52 { 53 mCondition = state; 54 } 55 56 /** 57 * Open the condition, and release all threads that are blocked. 58 * 59 * <p> 60 * Any threads that later approach block() will not block unless close() 61 * is called. 62 */ open()63 public void open() 64 { 65 synchronized (this) { 66 boolean old = mCondition; 67 mCondition = true; 68 if (!old) { 69 this.notifyAll(); 70 } 71 } 72 } 73 74 /** 75 * Reset the condition to the closed state. 76 * 77 * <p> 78 * Any threads that call block() will block until someone calls open. 79 */ close()80 public void close() 81 { 82 synchronized (this) { 83 mCondition = false; 84 } 85 } 86 87 /** 88 * Block the current thread until the condition is opened. 89 * 90 * <p> 91 * If the condition is already opened, return immediately. 92 */ block()93 public void block() 94 { 95 synchronized (this) { 96 while (!mCondition) { 97 try { 98 this.wait(); 99 } 100 catch (InterruptedException e) { 101 } 102 } 103 } 104 } 105 106 /** 107 * Block the current thread until the condition is opened or until 108 * timeoutMs milliseconds have passed. 109 * 110 * <p> 111 * If the condition is already opened, return immediately. 112 * 113 * @param timeoutMs the maximum time to wait in milliseconds. 114 * 115 * @return true if the condition was opened, false if the call returns 116 * because of the timeout. 117 */ block(long timeoutMs)118 public boolean block(long timeoutMs) 119 { 120 // Object.wait(0) means wait forever, to mimic this, we just 121 // call the other block() method in that case. It simplifies 122 // this code for the common case. 123 if (timeoutMs != 0) { 124 synchronized (this) { 125 long now = SystemClock.elapsedRealtime(); 126 long end = now + timeoutMs; 127 while (!mCondition && now < end) { 128 try { 129 this.wait(end-now); 130 } 131 catch (InterruptedException e) { 132 } 133 now = SystemClock.elapsedRealtime(); 134 } 135 return mCondition; 136 } 137 } else { 138 this.block(); 139 return true; 140 } 141 } 142 } 143