From a84ecfd1f81f7b2989852631d182d6898a2af32d Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Tue, 21 Aug 2012 13:02:43 +0800 Subject: Move ThreadPool to gallerycommon for picasasync and picasastore. Bug: 7005321 Change-Id: I7ae4bafed141be03bca74772a261c7c2fb3036c4 --- .../src/com/android/gallery3d/util/Future.java | 35 +++ .../com/android/gallery3d/util/FutureListener.java | 21 ++ .../gallery3d/util/PriorityThreadFactory.java | 49 ++++ .../src/com/android/gallery3d/util/ThreadPool.java | 264 +++++++++++++++++++++ src/com/android/gallery3d/util/Future.java | 35 --- src/com/android/gallery3d/util/FutureListener.java | 21 -- .../gallery3d/util/PriorityThreadFactory.java | 49 ---- src/com/android/gallery3d/util/ThreadPool.java | 262 -------------------- 8 files changed, 369 insertions(+), 367 deletions(-) create mode 100644 gallerycommon/src/com/android/gallery3d/util/Future.java create mode 100644 gallerycommon/src/com/android/gallery3d/util/FutureListener.java create mode 100644 gallerycommon/src/com/android/gallery3d/util/PriorityThreadFactory.java create mode 100644 gallerycommon/src/com/android/gallery3d/util/ThreadPool.java delete mode 100644 src/com/android/gallery3d/util/Future.java delete mode 100644 src/com/android/gallery3d/util/FutureListener.java delete mode 100644 src/com/android/gallery3d/util/PriorityThreadFactory.java delete mode 100644 src/com/android/gallery3d/util/ThreadPool.java diff --git a/gallerycommon/src/com/android/gallery3d/util/Future.java b/gallerycommon/src/com/android/gallery3d/util/Future.java new file mode 100644 index 000000000..580a2a120 --- /dev/null +++ b/gallerycommon/src/com/android/gallery3d/util/Future.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 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 com.android.gallery3d.util; + +// This Future differs from the java.util.concurrent.Future in these aspects: +// +// - Once cancel() is called, isCancelled() always returns true. It is a sticky +// flag used to communicate to the implementation. The implmentation may +// ignore that flag. Regardless whether the Future is cancelled, a return +// value will be provided to get(). The implementation may choose to return +// null if it finds the Future is cancelled. +// +// - get() does not throw exceptions. +// +public interface Future { + public void cancel(); + public boolean isCancelled(); + public boolean isDone(); + public T get(); + public void waitDone(); +} diff --git a/gallerycommon/src/com/android/gallery3d/util/FutureListener.java b/gallerycommon/src/com/android/gallery3d/util/FutureListener.java new file mode 100644 index 000000000..ed1f820c7 --- /dev/null +++ b/gallerycommon/src/com/android/gallery3d/util/FutureListener.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 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 com.android.gallery3d.util; + +public interface FutureListener { + public void onFutureDone(Future future); +} diff --git a/gallerycommon/src/com/android/gallery3d/util/PriorityThreadFactory.java b/gallerycommon/src/com/android/gallery3d/util/PriorityThreadFactory.java new file mode 100644 index 000000000..30d8e4a96 --- /dev/null +++ b/gallerycommon/src/com/android/gallery3d/util/PriorityThreadFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 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 com.android.gallery3d.util; + + +import android.os.Process; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A thread factory that creates threads with a given thread priority. + */ +public class PriorityThreadFactory implements ThreadFactory { + + private final int mPriority; + private final AtomicInteger mNumber = new AtomicInteger(); + private final String mName; + + public PriorityThreadFactory(String name, int priority) { + mName = name; + mPriority = priority; + } + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, mName + '-' + mNumber.getAndIncrement()) { + @Override + public void run() { + Process.setThreadPriority(mPriority); + super.run(); + } + }; + } + +} diff --git a/gallerycommon/src/com/android/gallery3d/util/ThreadPool.java b/gallerycommon/src/com/android/gallery3d/util/ThreadPool.java new file mode 100644 index 000000000..cada234b3 --- /dev/null +++ b/gallerycommon/src/com/android/gallery3d/util/ThreadPool.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2010 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 com.android.gallery3d.util; + +import android.util.Log; + +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPool { + @SuppressWarnings("unused") + private static final String TAG = "ThreadPool"; + private static final int CORE_POOL_SIZE = 4; + private static final int MAX_POOL_SIZE = 8; + private static final int KEEP_ALIVE_TIME = 10; // 10 seconds + + // Resource type + public static final int MODE_NONE = 0; + public static final int MODE_CPU = 1; + public static final int MODE_NETWORK = 2; + + public static final JobContext JOB_CONTEXT_STUB = new JobContextStub(); + + ResourceCounter mCpuCounter = new ResourceCounter(2); + ResourceCounter mNetworkCounter = new ResourceCounter(2); + + // A Job is like a Callable, but it has an addition JobContext parameter. + public interface Job { + public T run(JobContext jc); + } + + public interface JobContext { + boolean isCancelled(); + void setCancelListener(CancelListener listener); + boolean setMode(int mode); + } + + private static class JobContextStub implements JobContext { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void setCancelListener(CancelListener listener) { + } + + @Override + public boolean setMode(int mode) { + return true; + } + } + + public interface CancelListener { + public void onCancel(); + } + + private static class ResourceCounter { + public int value; + public ResourceCounter(int v) { + value = v; + } + } + + private final Executor mExecutor; + + public ThreadPool() { + mExecutor = new ThreadPoolExecutor( + CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, + TimeUnit.SECONDS, new LinkedBlockingQueue(), + new PriorityThreadFactory("thread-pool", + android.os.Process.THREAD_PRIORITY_BACKGROUND)); + } + + // Submit a job to the thread pool. The listener will be called when the + // job is finished (or cancelled). + public Future submit(Job job, FutureListener listener) { + Worker w = new Worker(job, listener); + mExecutor.execute(w); + return w; + } + + public Future submit(Job job) { + return submit(job, null); + } + + private class Worker implements Runnable, Future, JobContext { + @SuppressWarnings("hiding") + private static final String TAG = "Worker"; + private Job mJob; + private FutureListener mListener; + private CancelListener mCancelListener; + private ResourceCounter mWaitOnResource; + private volatile boolean mIsCancelled; + private boolean mIsDone; + private T mResult; + private int mMode; + + public Worker(Job job, FutureListener listener) { + mJob = job; + mListener = listener; + } + + // This is called by a thread in the thread pool. + @Override + public void run() { + T result = null; + + // A job is in CPU mode by default. setMode returns false + // if the job is cancelled. + if (setMode(MODE_CPU)) { + try { + result = mJob.run(this); + } catch (Throwable ex) { + Log.w(TAG, "Exception in running a job", ex); + } + } + + synchronized(this) { + setMode(MODE_NONE); + mResult = result; + mIsDone = true; + notifyAll(); + } + if (mListener != null) mListener.onFutureDone(this); + } + + // Below are the methods for Future. + @Override + public synchronized void cancel() { + if (mIsCancelled) return; + mIsCancelled = true; + if (mWaitOnResource != null) { + synchronized (mWaitOnResource) { + mWaitOnResource.notifyAll(); + } + } + if (mCancelListener != null) { + mCancelListener.onCancel(); + } + } + + @Override + public boolean isCancelled() { + return mIsCancelled; + } + + @Override + public synchronized boolean isDone() { + return mIsDone; + } + + @Override + public synchronized T get() { + while (!mIsDone) { + try { + wait(); + } catch (Exception ex) { + Log.w(TAG, "ingore exception", ex); + // ignore. + } + } + return mResult; + } + + @Override + public void waitDone() { + get(); + } + + // Below are the methods for JobContext (only called from the + // thread running the job) + @Override + public synchronized void setCancelListener(CancelListener listener) { + mCancelListener = listener; + if (mIsCancelled && mCancelListener != null) { + mCancelListener.onCancel(); + } + } + + @Override + public boolean setMode(int mode) { + // Release old resource + ResourceCounter rc = modeToCounter(mMode); + if (rc != null) releaseResource(rc); + mMode = MODE_NONE; + + // Acquire new resource + rc = modeToCounter(mode); + if (rc != null) { + if (!acquireResource(rc)) { + return false; + } + mMode = mode; + } + + return true; + } + + private ResourceCounter modeToCounter(int mode) { + if (mode == MODE_CPU) { + return mCpuCounter; + } else if (mode == MODE_NETWORK) { + return mNetworkCounter; + } else { + return null; + } + } + + private boolean acquireResource(ResourceCounter counter) { + while (true) { + synchronized (this) { + if (mIsCancelled) { + mWaitOnResource = null; + return false; + } + mWaitOnResource = counter; + } + + synchronized (counter) { + if (counter.value > 0) { + counter.value--; + break; + } else { + try { + counter.wait(); + } catch (InterruptedException ex) { + // ignore. + } + } + } + } + + synchronized (this) { + mWaitOnResource = null; + } + + return true; + } + + private void releaseResource(ResourceCounter counter) { + synchronized (counter) { + counter.value++; + counter.notifyAll(); + } + } + } +} diff --git a/src/com/android/gallery3d/util/Future.java b/src/com/android/gallery3d/util/Future.java deleted file mode 100644 index 580a2a120..000000000 --- a/src/com/android/gallery3d/util/Future.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010 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 com.android.gallery3d.util; - -// This Future differs from the java.util.concurrent.Future in these aspects: -// -// - Once cancel() is called, isCancelled() always returns true. It is a sticky -// flag used to communicate to the implementation. The implmentation may -// ignore that flag. Regardless whether the Future is cancelled, a return -// value will be provided to get(). The implementation may choose to return -// null if it finds the Future is cancelled. -// -// - get() does not throw exceptions. -// -public interface Future { - public void cancel(); - public boolean isCancelled(); - public boolean isDone(); - public T get(); - public void waitDone(); -} diff --git a/src/com/android/gallery3d/util/FutureListener.java b/src/com/android/gallery3d/util/FutureListener.java deleted file mode 100644 index ed1f820c7..000000000 --- a/src/com/android/gallery3d/util/FutureListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2010 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 com.android.gallery3d.util; - -public interface FutureListener { - public void onFutureDone(Future future); -} diff --git a/src/com/android/gallery3d/util/PriorityThreadFactory.java b/src/com/android/gallery3d/util/PriorityThreadFactory.java deleted file mode 100644 index 30d8e4a96..000000000 --- a/src/com/android/gallery3d/util/PriorityThreadFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 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 com.android.gallery3d.util; - - -import android.os.Process; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A thread factory that creates threads with a given thread priority. - */ -public class PriorityThreadFactory implements ThreadFactory { - - private final int mPriority; - private final AtomicInteger mNumber = new AtomicInteger(); - private final String mName; - - public PriorityThreadFactory(String name, int priority) { - mName = name; - mPriority = priority; - } - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, mName + '-' + mNumber.getAndIncrement()) { - @Override - public void run() { - Process.setThreadPriority(mPriority); - super.run(); - } - }; - } - -} diff --git a/src/com/android/gallery3d/util/ThreadPool.java b/src/com/android/gallery3d/util/ThreadPool.java deleted file mode 100644 index 4c077c8f3..000000000 --- a/src/com/android/gallery3d/util/ThreadPool.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2010 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 com.android.gallery3d.util; - -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class ThreadPool { - @SuppressWarnings("unused") - private static final String TAG = "ThreadPool"; - private static final int CORE_POOL_SIZE = 4; - private static final int MAX_POOL_SIZE = 8; - private static final int KEEP_ALIVE_TIME = 10; // 10 seconds - - // Resource type - public static final int MODE_NONE = 0; - public static final int MODE_CPU = 1; - public static final int MODE_NETWORK = 2; - - public static final JobContext JOB_CONTEXT_STUB = new JobContextStub(); - - ResourceCounter mCpuCounter = new ResourceCounter(2); - ResourceCounter mNetworkCounter = new ResourceCounter(2); - - // A Job is like a Callable, but it has an addition JobContext parameter. - public interface Job { - public T run(JobContext jc); - } - - public interface JobContext { - boolean isCancelled(); - void setCancelListener(CancelListener listener); - boolean setMode(int mode); - } - - private static class JobContextStub implements JobContext { - @Override - public boolean isCancelled() { - return false; - } - - @Override - public void setCancelListener(CancelListener listener) { - } - - @Override - public boolean setMode(int mode) { - return true; - } - } - - public interface CancelListener { - public void onCancel(); - } - - private static class ResourceCounter { - public int value; - public ResourceCounter(int v) { - value = v; - } - } - - private final Executor mExecutor; - - public ThreadPool() { - mExecutor = new ThreadPoolExecutor( - CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, - TimeUnit.SECONDS, new LinkedBlockingQueue(), - new PriorityThreadFactory("thread-pool", - android.os.Process.THREAD_PRIORITY_BACKGROUND)); - } - - // Submit a job to the thread pool. The listener will be called when the - // job is finished (or cancelled). - public Future submit(Job job, FutureListener listener) { - Worker w = new Worker(job, listener); - mExecutor.execute(w); - return w; - } - - public Future submit(Job job) { - return submit(job, null); - } - - private class Worker implements Runnable, Future, JobContext { - @SuppressWarnings("hiding") - private static final String TAG = "Worker"; - private Job mJob; - private FutureListener mListener; - private CancelListener mCancelListener; - private ResourceCounter mWaitOnResource; - private volatile boolean mIsCancelled; - private boolean mIsDone; - private T mResult; - private int mMode; - - public Worker(Job job, FutureListener listener) { - mJob = job; - mListener = listener; - } - - // This is called by a thread in the thread pool. - @Override - public void run() { - T result = null; - - // A job is in CPU mode by default. setMode returns false - // if the job is cancelled. - if (setMode(MODE_CPU)) { - try { - result = mJob.run(this); - } catch (Throwable ex) { - Log.w(TAG, "Exception in running a job", ex); - } - } - - synchronized(this) { - setMode(MODE_NONE); - mResult = result; - mIsDone = true; - notifyAll(); - } - if (mListener != null) mListener.onFutureDone(this); - } - - // Below are the methods for Future. - @Override - public synchronized void cancel() { - if (mIsCancelled) return; - mIsCancelled = true; - if (mWaitOnResource != null) { - synchronized (mWaitOnResource) { - mWaitOnResource.notifyAll(); - } - } - if (mCancelListener != null) { - mCancelListener.onCancel(); - } - } - - @Override - public boolean isCancelled() { - return mIsCancelled; - } - - @Override - public synchronized boolean isDone() { - return mIsDone; - } - - @Override - public synchronized T get() { - while (!mIsDone) { - try { - wait(); - } catch (Exception ex) { - Log.w(TAG, "ingore exception", ex); - // ignore. - } - } - return mResult; - } - - @Override - public void waitDone() { - get(); - } - - // Below are the methods for JobContext (only called from the - // thread running the job) - @Override - public synchronized void setCancelListener(CancelListener listener) { - mCancelListener = listener; - if (mIsCancelled && mCancelListener != null) { - mCancelListener.onCancel(); - } - } - - @Override - public boolean setMode(int mode) { - // Release old resource - ResourceCounter rc = modeToCounter(mMode); - if (rc != null) releaseResource(rc); - mMode = MODE_NONE; - - // Acquire new resource - rc = modeToCounter(mode); - if (rc != null) { - if (!acquireResource(rc)) { - return false; - } - mMode = mode; - } - - return true; - } - - private ResourceCounter modeToCounter(int mode) { - if (mode == MODE_CPU) { - return mCpuCounter; - } else if (mode == MODE_NETWORK) { - return mNetworkCounter; - } else { - return null; - } - } - - private boolean acquireResource(ResourceCounter counter) { - while (true) { - synchronized (this) { - if (mIsCancelled) { - mWaitOnResource = null; - return false; - } - mWaitOnResource = counter; - } - - synchronized (counter) { - if (counter.value > 0) { - counter.value--; - break; - } else { - try { - counter.wait(); - } catch (InterruptedException ex) { - // ignore. - } - } - } - } - - synchronized (this) { - mWaitOnResource = null; - } - - return true; - } - - private void releaseResource(ResourceCounter counter) { - synchronized (counter) { - counter.value++; - counter.notifyAll(); - } - } - } -} -- cgit v1.2.3