summaryrefslogtreecommitdiffstats
path: root/runtime/thread_pool_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/thread_pool_test.cc')
-rw-r--r--runtime/thread_pool_test.cc144
1 files changed, 144 insertions, 0 deletions
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
new file mode 100644
index 0000000..e2a32f5
--- /dev/null
+++ b/runtime/thread_pool_test.cc
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+
+#include <string>
+
+#include "atomic_integer.h"
+#include "common_test.h"
+#include "thread_pool.h"
+
+namespace art {
+
+class CountTask : public Task {
+ public:
+ CountTask(AtomicInteger* count) : count_(count), verbose_(false) {
+ }
+
+ void Run(Thread* self) {
+ if (verbose_) {
+ LOG(INFO) << "Running: " << *self;
+ }
+ // Simulate doing some work.
+ usleep(100);
+ // Increment the counter which keeps track of work completed.
+ ++*count_;
+ }
+
+ void Finalize() {
+ if (verbose_) {
+ LOG(INFO) << "Finalizing: " << *Thread::Current();
+ }
+ delete this;
+ }
+
+ private:
+ AtomicInteger* const count_;
+ const bool verbose_;
+};
+
+class ThreadPoolTest : public CommonTest {
+ public:
+ static int32_t num_threads;
+};
+
+int32_t ThreadPoolTest::num_threads = 4;
+
+// Check that the thread pool actually runs tasks that you assign it.
+TEST_F(ThreadPoolTest, CheckRun) {
+ Thread* self = Thread::Current();
+ ThreadPool thread_pool(num_threads);
+ AtomicInteger count = 0;
+ static const int32_t num_tasks = num_threads * 4;
+ for (int32_t i = 0; i < num_tasks; ++i) {
+ thread_pool.AddTask(self, new CountTask(&count));
+ }
+ thread_pool.StartWorkers(self);
+ // Wait for tasks to complete.
+ thread_pool.Wait(self, true, false);
+ // Make sure that we finished all the work.
+ EXPECT_EQ(num_tasks, count);
+}
+
+TEST_F(ThreadPoolTest, StopStart) {
+ Thread* self = Thread::Current();
+ ThreadPool thread_pool(num_threads);
+ AtomicInteger count = 0;
+ static const int32_t num_tasks = num_threads * 4;
+ for (int32_t i = 0; i < num_tasks; ++i) {
+ thread_pool.AddTask(self, new CountTask(&count));
+ }
+ usleep(200);
+ // Check that no threads started prematurely.
+ EXPECT_EQ(0, count);
+ // Signal the threads to start processing tasks.
+ thread_pool.StartWorkers(self);
+ usleep(200);
+ thread_pool.StopWorkers(self);
+ AtomicInteger bad_count = 0;
+ thread_pool.AddTask(self, new CountTask(&bad_count));
+ usleep(200);
+ // Ensure that the task added after the workers were stopped doesn't get run.
+ EXPECT_EQ(0, bad_count);
+ // Allow tasks to finish up and delete themselves.
+ thread_pool.StartWorkers(self);
+ while (count.get() != num_tasks && bad_count.get() != 1) {
+ usleep(200);
+ }
+ thread_pool.StopWorkers(self);
+}
+
+class TreeTask : public Task {
+ public:
+ TreeTask(ThreadPool* const thread_pool, AtomicInteger* count, int depth)
+ : thread_pool_(thread_pool),
+ count_(count),
+ depth_(depth) {
+
+ }
+
+ void Run(Thread* self) {
+ if (depth_ > 1) {
+ thread_pool_->AddTask(self, new TreeTask(thread_pool_, count_, depth_ - 1));
+ thread_pool_->AddTask(self, new TreeTask(thread_pool_, count_, depth_ - 1));
+ }
+ // Increment the counter which keeps track of work completed.
+ ++*count_;
+ }
+
+ void Finalize() {
+ delete this;
+ }
+
+ private:
+ ThreadPool* const thread_pool_;
+ AtomicInteger* const count_;
+ const int depth_;
+};
+
+// Test that adding new tasks from within a task works.
+TEST_F(ThreadPoolTest, RecursiveTest) {
+ Thread* self = Thread::Current();
+ ThreadPool thread_pool(num_threads);
+ AtomicInteger count = 0;
+ static const int depth = 8;
+ thread_pool.AddTask(self, new TreeTask(&thread_pool, &count, depth));
+ thread_pool.StartWorkers(self);
+ thread_pool.Wait(self, true, false);
+ EXPECT_EQ((1 << depth) - 1, count);
+}
+
+} // namespace art