|  | /* | 
|  | * Copyright (C) 2006 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | package android.os; | 
|  |  | 
|  | /** | 
|  | * Class that implements the condition variable locking paradigm. | 
|  | * | 
|  | * <p> | 
|  | * This differs from the built-in java.lang.Object wait() and notify() | 
|  | * in that this class contains the condition to wait on itself.  That means | 
|  | * open(), close() and block() are sticky.  If open() is called before block(), | 
|  | * block() will not block, and instead return immediately. | 
|  | * | 
|  | * <p> | 
|  | * This class uses itself as the object to wait on, so if you wait() | 
|  | * or notify() on a ConditionVariable, the results are undefined. | 
|  | */ | 
|  | public class ConditionVariable | 
|  | { | 
|  | private volatile boolean mCondition; | 
|  |  | 
|  | /** | 
|  | * Create the ConditionVariable in the default closed state. | 
|  | */ | 
|  | public ConditionVariable() | 
|  | { | 
|  | mCondition = false; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Create the ConditionVariable with the given state. | 
|  | * | 
|  | * <p> | 
|  | * Pass true for opened and false for closed. | 
|  | */ | 
|  | public ConditionVariable(boolean state) | 
|  | { | 
|  | mCondition = state; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Open the condition, and release all threads that are blocked. | 
|  | * | 
|  | * <p> | 
|  | * Any threads that later approach block() will not block unless close() | 
|  | * is called. | 
|  | */ | 
|  | public void open() | 
|  | { | 
|  | synchronized (this) { | 
|  | boolean old = mCondition; | 
|  | mCondition = true; | 
|  | if (!old) { | 
|  | this.notifyAll(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Reset the condition to the closed state. | 
|  | * | 
|  | * <p> | 
|  | * Any threads that call block() will block until someone calls open. | 
|  | */ | 
|  | public void close() | 
|  | { | 
|  | synchronized (this) { | 
|  | mCondition = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Block the current thread until the condition is opened. | 
|  | * | 
|  | * <p> | 
|  | * If the condition is already opened, return immediately. | 
|  | */ | 
|  | public void block() | 
|  | { | 
|  | synchronized (this) { | 
|  | while (!mCondition) { | 
|  | try { | 
|  | this.wait(); | 
|  | } | 
|  | catch (InterruptedException e) { | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Block the current thread until the condition is opened or until | 
|  | * timeout milliseconds have passed. | 
|  | * | 
|  | * <p> | 
|  | * If the condition is already opened, return immediately. | 
|  | * | 
|  | * @param timeout the maximum time to wait in milliseconds. | 
|  | * | 
|  | * @return true if the condition was opened, false if the call returns | 
|  | * because of the timeout. | 
|  | */ | 
|  | public boolean block(long timeout) | 
|  | { | 
|  | // Object.wait(0) means wait forever, to mimic this, we just | 
|  | // call the other block() method in that case.  It simplifies | 
|  | // this code for the common case. | 
|  | if (timeout != 0) { | 
|  | synchronized (this) { | 
|  | long now = System.currentTimeMillis(); | 
|  | long end = now + timeout; | 
|  | while (!mCondition && now < end) { | 
|  | try { | 
|  | this.wait(end-now); | 
|  | } | 
|  | catch (InterruptedException e) { | 
|  | } | 
|  | now = System.currentTimeMillis(); | 
|  | } | 
|  | return mCondition; | 
|  | } | 
|  | } else { | 
|  | this.block(); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } |