Skip to content

Commit

Permalink
Support: Remove MSVC 2013 workarounds in ThreadPool class.
Browse files Browse the repository at this point in the history
I have confirmed that these are no longer needed with MSVC 2015.

Differential Revision: https://reviews.llvm.org/D34187

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305347 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
pcc committed Jun 14, 2017
1 parent f1e7673 commit 08c98a9
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 41 deletions.
28 changes: 3 additions & 25 deletions include/llvm/Support/ThreadPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,8 @@ namespace llvm {
/// for some work to become available.
class ThreadPool {
public:
#ifndef _MSC_VER
using VoidTy = void;
using TaskTy = std::function<void()>;
using PackagedTaskTy = std::packaged_task<void()>;
#else
// MSVC 2013 has a bug and can't use std::packaged_task<void()>;
// We force it to use bool(bool) instead.
using VoidTy = bool;
using TaskTy = std::function<bool(bool)>;
using PackagedTaskTy = std::packaged_task<bool(bool)>;
#endif

/// Construct a pool with the number of core available on the system (or
/// whatever the value returned by std::thread::hardware_concurrency() is).
Expand All @@ -60,30 +51,17 @@ class ThreadPool {
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function, typename... Args>
inline std::shared_future<VoidTy> async(Function &&F, Args &&... ArgList) {
inline std::shared_future<void> async(Function &&F, Args &&... ArgList) {
auto Task =
std::bind(std::forward<Function>(F), std::forward<Args>(ArgList)...);
#ifndef _MSC_VER
return asyncImpl(std::move(Task));
#else
// This lambda has to be marked mutable because MSVC 2013's std::bind call
// operator isn't const qualified.
return asyncImpl([Task](VoidTy) mutable -> VoidTy {
Task();
return VoidTy();
});
#endif
}

/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function>
inline std::shared_future<VoidTy> async(Function &&F) {
#ifndef _MSC_VER
inline std::shared_future<void> async(Function &&F) {
return asyncImpl(std::forward<Function>(F));
#else
return asyncImpl([F] (VoidTy) -> VoidTy { F(); return VoidTy(); });
#endif
}

/// Blocking wait for all the threads to complete and the queue to be empty.
Expand All @@ -93,7 +71,7 @@ class ThreadPool {
private:
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
std::shared_future<VoidTy> asyncImpl(TaskTy F);
std::shared_future<void> asyncImpl(TaskTy F);

/// Threads in flight
std::vector<llvm::thread> Threads;
Expand Down
19 changes: 3 additions & 16 deletions lib/Support/ThreadPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ ThreadPool::ThreadPool(unsigned ThreadCount)
Tasks.pop();
}
// Run the task we just grabbed
#ifndef _MSC_VER
Task();
#else
Task(/* unused */ false);
#endif

{
// Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()
Expand All @@ -82,7 +78,7 @@ void ThreadPool::wait() {
[&] { return !ActiveThreads && Tasks.empty(); });
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
/// Wrap the Task in a packaged_task to return a future object.
PackagedTaskTy PackagedTask(std::move(Task));
auto Future = PackagedTask.get_future();
Expand Down Expand Up @@ -128,25 +124,16 @@ void ThreadPool::wait() {
while (!Tasks.empty()) {
auto Task = std::move(Tasks.front());
Tasks.pop();
#ifndef _MSC_VER
Task();
#else
Task(/* unused */ false);
#endif
Task();
}
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
#ifndef _MSC_VER
std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
// Get a Future with launch::deferred execution using std::async
auto Future = std::async(std::launch::deferred, std::move(Task)).share();
// Wrap the future so that both ThreadPool::wait() can operate and the
// returned future can be sync'ed on.
PackagedTaskTy PackagedTask([Future]() { Future.get(); });
#else
auto Future = std::async(std::launch::deferred, std::move(Task), false).share();
PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; });
#endif
Tasks.push(std::move(PackagedTask));
return Future;
}
Expand Down

0 comments on commit 08c98a9

Please sign in to comment.