blob: fea3cd60eda58c8b89d5a5a9dce0a88ad99eb329 [file]
//===- ThreadPoolRunner.cpp -----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Contains the implementation of APIs in the orc-rt/ThreadPoolRunner.h
// header.
//
//===----------------------------------------------------------------------===//
#include "orc-rt/ThreadPoolRunner.h"
#include <cassert>
namespace orc_rt {
ThreadPoolRunner::ThreadPoolRunner(size_t NumThreads) {
Workers.reserve(NumThreads);
for (size_t I = 0; I < NumThreads; ++I)
Workers.emplace_back([this]() { workerLoop(); });
}
ThreadPoolRunner::~ThreadPoolRunner() {
{
std::scoped_lock<std::mutex> Lock(M);
Stop = true;
}
CV.notify_all();
for (auto &Worker : Workers)
Worker.join();
}
void ThreadPoolRunner::operator()(orc_rt_SessionRef S, uint64_t CallId,
orc_rt_WrapperFunctionReturn Return,
orc_rt_WrapperFunction Fn,
WrapperFunctionBuffer ArgBytes) {
{
std::scoped_lock<std::mutex> Lock(M);
assert(!Stop &&
"operator() called on ThreadPoolRunner after destruction begun");
Pending.push_back([=, ArgBytes = std::move(ArgBytes)]() mutable {
Fn(S, CallId, Return, ArgBytes.release());
});
}
CV.notify_one();
}
void ThreadPoolRunner::workerLoop() {
while (true) {
move_only_function<void()> Call;
{
std::unique_lock<std::mutex> Lock(M);
CV.wait(Lock, [this]() { return !Pending.empty() || Stop; });
if (Pending.empty() && Stop)
return;
Call = std::move(Pending.back());
Pending.pop_back();
}
Call();
}
}
} // namespace orc_rt