forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			108 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
//========- unittests/Support/TaskQueue.cpp - TaskQueue.h tests ------========//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/Config/llvm-config.h"
 | 
						|
 | 
						|
#if LLVM_ENABLE_THREADS
 | 
						|
 | 
						|
#include "llvm/Support/TaskQueue.h"
 | 
						|
 | 
						|
#include "gtest/gtest.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
class TaskQueueTest : public testing::Test {
 | 
						|
protected:
 | 
						|
  TaskQueueTest() {}
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(TaskQueueTest, OrderedFutures) {
 | 
						|
  ThreadPool TP(hardware_concurrency(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(hardware_concurrency(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(hardware_concurrency(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
 |