summaryrefslogtreecommitdiffstats
path: root/include/utils
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-03-16 22:18:39 -0700
committerJeff Brown <jeffbrown@google.com>2012-03-17 14:28:38 -0700
commit0818b0921ef6cda07f41b56d2ef19b2849dfefd1 (patch)
tree03045f51fb101a838e3ccfa28c9ba8686f7558ce /include/utils
parente6d77c593d1a25b45c23bf9292ec7ee09fc14b6e (diff)
downloadframeworks_native-0818b0921ef6cda07f41b56d2ef19b2849dfefd1.zip
frameworks_native-0818b0921ef6cda07f41b56d2ef19b2849dfefd1.tar.gz
frameworks_native-0818b0921ef6cda07f41b56d2ef19b2849dfefd1.tar.bz2
Add a simple work queue abstraction.
Makes it easy to schedule a bunch of work to happen in parallel. Change-Id: Id9c0e52fc8b6d78d2b9ed4c2ee47abce0a01775c
Diffstat (limited to 'include/utils')
-rw-r--r--include/utils/AndroidThreads.h2
-rw-r--r--include/utils/WorkQueue.h119
2 files changed, 121 insertions, 0 deletions
diff --git a/include/utils/AndroidThreads.h b/include/utils/AndroidThreads.h
index f9f7aa4..5bda0fd 100644
--- a/include/utils/AndroidThreads.h
+++ b/include/utils/AndroidThreads.h
@@ -73,6 +73,7 @@ extern void androidSetCreateThreadFunc(android_create_thread_fn func);
// Get pid for the current thread.
extern pid_t androidGetTid();
+#ifdef HAVE_ANDROID_OS
// Change the scheduling group of a particular thread. The group
// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
// grp is out of range, else another non-zero value with errno set if
@@ -95,6 +96,7 @@ extern int androidGetThreadPriority(pid_t tid);
// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
// Thread ID zero means current thread.
extern int androidGetThreadSchedulingGroup(pid_t tid);
+#endif
#ifdef __cplusplus
} // extern "C"
diff --git a/include/utils/WorkQueue.h b/include/utils/WorkQueue.h
new file mode 100644
index 0000000..e3c75b2
--- /dev/null
+++ b/include/utils/WorkQueue.h
@@ -0,0 +1,119 @@
+/*]
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _LIBS_UTILS_WORK_QUEUE_H
+#define _LIBS_UTILS_WORK_QUEUE_H
+
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+/*
+ * A threaded work queue.
+ *
+ * This class is designed to make it easy to run a bunch of isolated work
+ * units in parallel, using up to the specified number of threads.
+ * To use it, write a loop to post work units to the work queue, then synchronize
+ * on the queue at the end.
+ */
+class WorkQueue {
+public:
+ class WorkUnit {
+ public:
+ WorkUnit() { }
+ virtual ~WorkUnit() { }
+
+ /*
+ * Runs the work unit.
+ * If the result is 'true' then the work queue continues scheduling work as usual.
+ * If the result is 'false' then the work queue is canceled.
+ */
+ virtual bool run() = 0;
+ };
+
+ /* Creates a work queue with the specified maximum number of work threads. */
+ WorkQueue(size_t maxThreads, bool canCallJava = true);
+
+ /* Destroys the work queue.
+ * Cancels pending work and waits for all remaining threads to complete.
+ */
+ ~WorkQueue();
+
+ /* Posts a work unit to run later.
+ * If the work queue has been canceled or is already finished, returns INVALID_OPERATION
+ * and does not take ownership of the work unit (caller must destroy it itself).
+ * Otherwise, returns OK and takes ownership of the work unit (the work queue will
+ * destroy it automatically).
+ *
+ * For flow control, this method blocks when the size of the pending work queue is more
+ * 'backlog' times the number of threads. This condition reduces the rate of entry into
+ * the pending work queue and prevents it from growing much more rapidly than the
+ * work threads can actually handle.
+ *
+ * If 'backlog' is 0, then no throttle is applied.
+ */
+ status_t schedule(WorkUnit* workUnit, size_t backlog = 2);
+
+ /* Cancels all pending work.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * If the work queue is already canceled, returns OK and does nothing else.
+ * Otherwise, returns OK, discards all pending work units and prevents additional
+ * work units from being scheduled.
+ *
+ * Call finish() after cancel() to wait for all remaining work to complete.
+ */
+ status_t cancel();
+
+ /* Waits for all work to complete.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * Otherwise, waits for all work to complete and returns OK.
+ */
+ status_t finish();
+
+private:
+ class WorkThread : public Thread {
+ public:
+ WorkThread(WorkQueue* workQueue, bool canCallJava);
+ virtual ~WorkThread();
+
+ private:
+ virtual bool threadLoop();
+
+ WorkQueue* const mWorkQueue;
+ };
+
+ status_t cancelLocked();
+ bool threadLoop(); // called from each work thread
+
+ const size_t mMaxThreads;
+ const bool mCanCallJava;
+
+ Mutex mLock;
+ Condition mWorkChangedCondition;
+ Condition mWorkDequeuedCondition;
+
+ bool mCanceled;
+ bool mFinished;
+ size_t mIdleThreads;
+ Vector<sp<WorkThread> > mWorkThreads;
+ Vector<WorkUnit*> mWorkUnits;
+};
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_WORK_QUEUE_H