Home | History | Annotate | Download | only in os
      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      */
     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      */
     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      */
     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      */
     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      */
     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      * timeout milliseconds have passed.
    108      *
    109      * <p>
    110      * If the condition is already opened, return immediately.
    111      *
    112      * @param timeout 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      */
    117     public boolean block(long timeout)
    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 (timeout != 0) {
    123             synchronized (this) {
    124                 long now = System.currentTimeMillis();
    125                 long end = now + timeout;
    126                 while (!mCondition && now < end) {
    127                     try {
    128                         this.wait(end-now);
    129                     }
    130                     catch (InterruptedException e) {
    131                     }
    132                     now = System.currentTimeMillis();
    133                 }
    134                 return mCondition;
    135             }
    136         } else {
    137             this.block();
    138             return true;
    139         }
    140     }
    141 }
    142