summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Support
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-06-25 03:13:09 +0000
committerZachary Turner <zturner@google.com>2018-06-25 03:13:09 +0000
commit35169f66988223c2b44e211fe10e21c6ac3e7ddc (patch)
tree1e3fad7d006b994974f86e2de27e731c9290e386 /llvm/unittests/Support
parent04c48949116d2e3407f76856476c00417abdb076 (diff)
downloadbcm5719-llvm-35169f66988223c2b44e211fe10e21c6ac3e7ddc.tar.gz
bcm5719-llvm-35169f66988223c2b44e211fe10e21c6ac3e7ddc.zip
Add a TaskQueue that can serialize work on a ThreadPool.
We have ThreadPool, which can execute work asynchronously on N background threads, but sometimes you need to make sure the work is executed asynchronously but also serially. That is, if task B is enqueued after task A, then task B should not begin until task A has completed. This patch adds such a class. Differential Revision: https://reviews.llvm.org/D48240 llvm-svn: 335440
Diffstat (limited to 'llvm/unittests/Support')
-rw-r--r--llvm/unittests/Support/CMakeLists.txt1
-rw-r--r--llvm/unittests/Support/TaskQueueTest.cpp105
2 files changed, 106 insertions, 0 deletions
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 4b46387a471..655ca7fb9b4 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -53,6 +53,7 @@ add_llvm_unittest(SupportTests
SwapByteOrderTest.cpp
TarWriterTest.cpp
TargetParserTest.cpp
+ TaskQueueTest.cpp
ThreadLocalTest.cpp
ThreadPool.cpp
Threading.cpp
diff --git a/llvm/unittests/Support/TaskQueueTest.cpp b/llvm/unittests/Support/TaskQueueTest.cpp
new file mode 100644
index 00000000000..ad7f5b51515
--- /dev/null
+++ b/llvm/unittests/Support/TaskQueueTest.cpp
@@ -0,0 +1,105 @@
+//========- unittests/Support/TaskQueue.cpp - TaskQueue.h tests ------========//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TaskQueue.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+#if LLVM_ENABLE_THREADS
+class TaskQueueTest : public testing::Test {
+protected:
+ TaskQueueTest() {}
+};
+
+TEST_F(TaskQueueTest, OrderedFutures) {
+ ThreadPool TP(1);
+ TaskQueue TQ(TP);
+ std::atomic<int> X = 0;
+ std::atomic<int> Y = 0;
+ std::atomic<int> Z = 0;
+
+ std::mutex M1, M2, M3;
+ std::unique_lock<std::mutex> L1(M1);
+ std::unique_lock<std::mutex> L2(M2);
+ std::unique_lock<std::mutex> L3(M3);
+
+ std::future<void> F1 = TQ.async([&] {
+ std::unique_lock<std::mutex> Lock(M1);
+ ++X;
+ });
+ std::future<void> F2 = TQ.async([&] {
+ std::unique_lock<std::mutex> Lock(M2);
+ ++Y;
+ });
+ std::future<void> F3 = TQ.async([&] {
+ std::unique_lock<std::mutex> Lock(M3);
+ ++Z;
+ });
+
+ L1.unlock();
+ F1.wait();
+ ASSERT_EQ(1, X);
+ ASSERT_EQ(0, Y);
+ ASSERT_EQ(0, Z);
+
+ L2.unlock();
+ F2.wait();
+ ASSERT_EQ(1, X);
+ ASSERT_EQ(1, Y);
+ ASSERT_EQ(0, Z);
+
+ L3.unlock();
+ F3.wait();
+ ASSERT_EQ(1, X);
+ ASSERT_EQ(1, Y);
+ ASSERT_EQ(1, Z);
+}
+
+TEST_F(TaskQueueTest, UnOrderedFutures) {
+ ThreadPool TP(1);
+ TaskQueue TQ(TP);
+ std::atomic<int> X = 0;
+ std::atomic<int> Y = 0;
+ std::atomic<int> Z = 0;
+ std::mutex M;
+
+ std::unique_lock<std::mutex> Lock(M);
+
+ std::future<void> F1 = TQ.async([&] { ++X; });
+ std::future<void> F2 = TQ.async([&] { ++Y; });
+ std::future<void> F3 = TQ.async([&M, &Z] {
+ std::unique_lock<std::mutex> Lock(M);
+ ++Z;
+ });
+
+ F2.wait();
+ ASSERT_EQ(1, X);
+ ASSERT_EQ(1, Y);
+ ASSERT_EQ(0, Z);
+
+ Lock.unlock();
+
+ F3.wait();
+ ASSERT_EQ(1, X);
+ ASSERT_EQ(1, Y);
+ ASSERT_EQ(1, Z);
+}
+
+TEST_F(TaskQueueTest, FutureWithReturnValue) {
+ ThreadPool TP(1);
+ TaskQueue TQ(TP);
+ std::future<std::string> F1 = TQ.async([&] { return std::string("Hello"); });
+ std::future<int> F2 = TQ.async([&] { return 42; });
+
+ ASSERT_EQ(42, F2.get());
+ ASSERT_EQ("Hello", F1.get());
+}
+#endif
OpenPOWER on IntegriCloud