ConditionVariable.java revision 14a9310efd936149c82ecfcc37c7c8308968f67c
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
17package 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 */
32public 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 minimum 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