1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.util;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19a7f90298629bc6549ffd60adadd387f6caee8c59Hung-ying Tyanimport android.util.Log;
20a7f90298629bc6549ffd60adadd387f6caee8c59Hung-ying Tyan
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.Executor;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.LinkedBlockingQueue;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.ThreadPoolExecutor;
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.TimeUnit;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class ThreadPool {
277817979db0c52ffeacb951625b1e821eba303285Ahbong Chang    @SuppressWarnings("unused")
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "ThreadPool";
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int CORE_POOL_SIZE = 4;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int MAX_POOL_SIZE = 8;
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int KEEP_ALIVE_TIME = 10; // 10 seconds
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Resource type
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final int MODE_NONE = 0;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final int MODE_CPU = 1;
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final int MODE_NETWORK = 2;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final JobContext JOB_CONTEXT_STUB = new JobContextStub();
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    ResourceCounter mCpuCounter = new ResourceCounter(2);
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    ResourceCounter mNetworkCounter = new ResourceCounter(2);
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // A Job is like a Callable, but it has an addition JobContext parameter.
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public interface Job<T> {
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public T run(JobContext jc);
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public interface JobContext {
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        boolean isCancelled();
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        void setCancelListener(CancelListener listener);
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        boolean setMode(int mode);
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class JobContextStub implements JobContext {
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean isCancelled() {
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return false;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void setCancelListener(CancelListener listener) {
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean setMode(int mode) {
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return true;
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public interface CancelListener {
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void onCancel();
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class ResourceCounter {
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int value;
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public ResourceCounter(int v) {
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            value = v;
78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final Executor mExecutor;
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public ThreadPool() {
84825afb1b3e7d15b5c258d664ee008dc68da1c407Mangesh Ghiware        this(CORE_POOL_SIZE, MAX_POOL_SIZE);
85825afb1b3e7d15b5c258d664ee008dc68da1c407Mangesh Ghiware    }
86825afb1b3e7d15b5c258d664ee008dc68da1c407Mangesh Ghiware
87825afb1b3e7d15b5c258d664ee008dc68da1c407Mangesh Ghiware    public ThreadPool(int initPoolSize, int maxPoolSize) {
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mExecutor = new ThreadPoolExecutor(
89825afb1b3e7d15b5c258d664ee008dc68da1c407Mangesh Ghiware                initPoolSize, maxPoolSize, KEEP_ALIVE_TIME,
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                new PriorityThreadFactory("thread-pool",
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                android.os.Process.THREAD_PRIORITY_BACKGROUND));
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Submit a job to the thread pool. The listener will be called when the
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // job is finished (or cancelled).
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public <T> Future<T> submit(Job<T> job, FutureListener<T> listener) {
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Worker<T> w = new Worker<T>(job, listener);
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mExecutor.execute(w);
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return w;
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public <T> Future<T> submit(Job<T> job) {
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return submit(job, null);
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private class Worker<T> implements Runnable, Future<T>, JobContext {
1087817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @SuppressWarnings("hiding")
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private static final String TAG = "Worker";
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private Job<T> mJob;
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private FutureListener<T> mListener;
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private CancelListener mCancelListener;
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private ResourceCounter mWaitOnResource;
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private volatile boolean mIsCancelled;
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private boolean mIsDone;
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private T mResult;
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private int mMode;
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Worker(Job<T> job, FutureListener<T> listener) {
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mJob = job;
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mListener = listener;
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // This is called by a thread in the thread pool.
1257817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void run() {
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            T result = null;
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // A job is in CPU mode by default. setMode returns false
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // if the job is cancelled.
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (setMode(MODE_CPU)) {
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                try {
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    result = mJob.run(this);
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                } catch (Throwable ex) {
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Log.w(TAG, "Exception in running a job", ex);
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized(this) {
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                setMode(MODE_NONE);
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mResult = result;
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mIsDone = true;
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                notifyAll();
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mListener != null) mListener.onFutureDone(this);
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // Below are the methods for Future.
1497817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public synchronized void cancel() {
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mIsCancelled) return;
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mIsCancelled = true;
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mWaitOnResource != null) {
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                synchronized (mWaitOnResource) {
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mWaitOnResource.notifyAll();
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mCancelListener != null) {
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mCancelListener.onCancel();
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1637817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean isCancelled() {
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mIsCancelled;
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1687817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public synchronized boolean isDone() {
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mIsDone;
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1737817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public synchronized T get() {
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            while (!mIsDone) {
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                try {
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    wait();
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                } catch (Exception ex) {
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Log.w(TAG, "ingore exception", ex);
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    // ignore.
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mResult;
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1867817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void waitDone() {
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            get();
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // Below are the methods for JobContext (only called from the
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // thread running the job)
1937817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public synchronized void setCancelListener(CancelListener listener) {
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCancelListener = listener;
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mIsCancelled && mCancelListener != null) {
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mCancelListener.onCancel();
198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2017817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean setMode(int mode) {
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // Release old resource
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            ResourceCounter rc = modeToCounter(mMode);
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (rc != null) releaseResource(rc);
206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMode = MODE_NONE;
207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // Acquire new resource
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            rc = modeToCounter(mode);
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (rc != null) {
211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                if (!acquireResource(rc)) {
212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    return false;
213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mMode = mode;
215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return true;
218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private ResourceCounter modeToCounter(int mode) {
221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mode == MODE_CPU) {
222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return mCpuCounter;
223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (mode == MODE_NETWORK) {
224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return mNetworkCounter;
225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return null;
227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private boolean acquireResource(ResourceCounter counter) {
231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            while (true) {
232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                synchronized (this) {
233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    if (mIsCancelled) {
234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        mWaitOnResource = null;
235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        return false;
236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mWaitOnResource = counter;
238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                synchronized (counter) {
241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    if (counter.value > 0) {
242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        counter.value--;
243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        break;
244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    } else {
245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        try {
246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                            counter.wait();
247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        } catch (InterruptedException ex) {
248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                            // ignore.
249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        }
250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized (this) {
255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mWaitOnResource = null;
256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return true;
259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private void releaseResource(ResourceCounter counter) {
262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized (counter) {
263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                counter.value++;
264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                counter.notifyAll();
265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
269