ConditionVariable.java revision 555f1986f106ccf1ec05f6e4118a19f9a6496dc5
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class that implements the condition variable locking paradigm. 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This differs from the built-in java.lang.Object wait() and notify() 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in that this class contains the condition to wait on itself. That means 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * open(), close() and block() are sticky. If open() is called before block(), 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * block() will not block, and instead return immediately. 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 2914a9310efd936149c82ecfcc37c7c8308968f67cPin Ting * This class uses itself as the object to wait on, so if you wait() 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or notify() on a ConditionVariable, the results are undefined. 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ConditionVariable 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile boolean mCondition; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create the ConditionVariable in the default closed state. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ConditionVariable() 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCondition = false; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create the ConditionVariable with the given state. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Pass true for opened and false for closed. 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ConditionVariable(boolean state) 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCondition = state; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the condition, and release all threads that are blocked. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Any threads that later approach block() will not block unless close() 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is called. 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void open() 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean old = mCondition; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCondition = true; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!old) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.notifyAll(); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reset the condition to the closed state. 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Any threads that call block() will block until someone calls open. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCondition = false; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Block the current thread until the condition is opened. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the condition is already opened, return immediately. 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void block() 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mCondition) { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Block the current thread until the condition is opened or until 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * timeout milliseconds have passed. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the condition is already opened, return immediately. 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 112555f1986f106ccf1ec05f6e4118a19f9a6496dc5Nicolas Prevot * @param timeout the maximum time to wait in milliseconds. 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the condition was opened, false if the call returns 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * because of the timeout. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean block(long timeout) 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Object.wait(0) means wait forever, to mimic this, we just 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // call the other block() method in that case. It simplifies 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this code for the common case. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (timeout != 0) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long end = now + timeout; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mCondition && now < end) { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(end-now); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project now = System.currentTimeMillis(); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCondition; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.block(); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 142