Add thread pool class

Added a thread pool class loosely based on google3 code.

Modified the compiler to have a single thread pool instead of creating new threads in ForAll.

Moved barrier to be in top level directory as it is not GC specific code.

Performance Timings:

Reference:
boot.oat: 14.306596s
time mm oat-target:
real    2m33.748s
user    10m23.190s
sys 5m54.140s

Thread pool:
boot.oat: 13.111049s
time mm oat-target:
real    2m29.372s
user    10m3.130s
sys 5m46.290s

The speed increase is probably just noise.

Change-Id: If3c1280cbaa4c7e4361127d064ac744ea12cdf49
diff --git a/src/barrier_test.cc b/src/barrier_test.cc
new file mode 100644
index 0000000..43b279e
--- /dev/null
+++ b/src/barrier_test.cc
@@ -0,0 +1,136 @@
+/*
+ * 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 "barrier.h"
+
+#include <string>
+
+#include "atomic_integer.h"
+#include "common_test.h"
+#include "thread_pool.h"
+#include "UniquePtr.h"
+
+namespace art {
+class CheckWaitClosure : public Closure {
+ public:
+  CheckWaitClosure(Barrier* barrier, AtomicInteger* count1, AtomicInteger* count2,
+                   AtomicInteger* count3)
+      : barrier_(barrier),
+        count1_(count1),
+        count2_(count2),
+        count3_(count3) {
+
+  }
+
+  void Run(Thread* self) {
+    LOG(INFO) << "Before barrier 1 " << self;
+    ++*count1_;
+    barrier_->Wait(self);
+    ++*count2_;
+    LOG(INFO) << "Before barrier 2 " << self;
+    barrier_->Wait(self);
+    ++*count3_;
+    LOG(INFO) << "After barrier 2 " << self;
+    delete this;
+  }
+ private:
+  Barrier* const barrier_;
+  AtomicInteger* const count1_;
+  AtomicInteger* const count2_;
+  AtomicInteger* const count3_;
+};
+
+class BarrierTest : public CommonTest {
+ public:
+  static int32_t num_threads;
+};
+
+int32_t BarrierTest::num_threads = 4;
+
+// Check that barrier wait and barrier increment work.
+TEST_F(BarrierTest, CheckWait) {
+  Thread* self = Thread::Current();
+  ThreadPool thread_pool(num_threads);
+  Barrier barrier;
+  AtomicInteger count1 = 0;
+  AtomicInteger count2 = 0;
+  AtomicInteger count3 = 0;
+  for (int32_t i = 0; i < num_threads; ++i) {
+    thread_pool.AddTask(self, new CheckWaitClosure(&barrier, &count1, &count2, &count3));
+  }
+  thread_pool.StartWorkers(self);
+  barrier.Increment(self, num_threads);
+  // At this point each thread should have passed through the barrier. The first count should be
+  // equal to num_threads.
+  EXPECT_EQ(num_threads, count1);
+  // Count 3 should still be zero since no thread should have gone past the second barrier.
+  EXPECT_EQ(0, count3);
+  // Now lets tell the threads to pass again.
+  barrier.Increment(self, num_threads);
+  // Count 2 should be equal to num_threads since each thread must have passed the second barrier
+  // at this point.
+  EXPECT_EQ(num_threads, count2);
+  // Wait for all the threads to finish.
+  thread_pool.Wait(self);
+  // All three counts should be equal to num_threads now.
+  EXPECT_EQ(count1, count2);
+  EXPECT_EQ(count2, count3);
+  EXPECT_EQ(num_threads, count3);
+}
+
+class CheckPassClosure : public Closure {
+ public:
+  CheckPassClosure(Barrier* barrier, AtomicInteger* count, size_t subtasks)
+      : barrier_(barrier),
+        count_(count),
+        subtasks_(subtasks) {
+
+  }
+
+  void Run(Thread* self) {
+    for (size_t i = 0; i < subtasks_; ++i) {
+      ++*count_;
+      // Pass through to next subtask.
+      barrier_->Pass(self);
+    }
+    delete this;
+  }
+ private:
+  Barrier* const barrier_;
+  AtomicInteger* const count_;
+  const size_t subtasks_;
+};
+
+// Check that barrier pass through works.
+TEST_F(BarrierTest, CheckPass) {
+  Thread* self = Thread::Current();
+  ThreadPool thread_pool(num_threads);
+  Barrier barrier;
+  AtomicInteger count = 0;
+  const int32_t num_tasks = num_threads * 4;
+  const int32_t num_sub_tasks = 128;
+  for (int32_t i = 0; i < num_tasks; ++i) {
+    thread_pool.AddTask(self, new CheckPassClosure(&barrier, &count, num_sub_tasks));
+  }
+  thread_pool.StartWorkers(self);
+  const int32_t expected_total_tasks = num_sub_tasks * num_tasks;
+  // Wait for all the tasks to complete using the barrier.
+  barrier.Increment(self, expected_total_tasks);
+  // The total number of completed tasks should be equal to expected_total_tasks.
+  EXPECT_EQ(count, expected_total_tasks);
+}
+
+}  // namespace art