11#include "llvm/Config/llvm-config.h"
28#if LLVM_ENABLE_THREADS
31static thread_local unsigned threadIndex = UINT_MAX;
35thread_local unsigned threadIndex = UINT_MAX;
45 virtual ~Executor() =
default;
46 virtual void add(std::function<
void()> func) = 0;
49 static Executor *getDefaultExecutor();
54class ThreadPoolExecutor :
public Executor {
65 std::lock_guard<std::mutex> Lock(
Mutex);
68 auto &Thread0 = Threads[0];
69 Thread0 = std::thread([
this, S] {
71 Threads.emplace_back([
this, S,
I] { work(S,
I); });
75 ThreadsCreated.set_value();
82 ThreadPoolExecutor() =
delete;
86 std::lock_guard<std::mutex> Lock(
Mutex);
92 ThreadsCreated.get_future().wait();
94 std::thread::id CurrentThreadId = std::this_thread::get_id();
95 for (std::thread &
T : Threads)
96 if (
T.get_id() == CurrentThreadId)
102 ~ThreadPoolExecutor()
override { stop(); }
105 static void *call() {
return new ThreadPoolExecutor(
strategy); }
108 static void call(
void *Ptr) { ((ThreadPoolExecutor *)Ptr)->stop(); }
111 void add(std::function<
void()>
F)
override {
113 std::lock_guard<std::mutex> Lock(
Mutex);
114 WorkStack.push_back(std::move(
F));
123 threadIndex = ThreadID;
147 Slot = TheJobserver->tryAcquire();
153 [&] { TheJobserver->release(std::move(Slot)); });
156 std::function<void()> Task;
158 std::unique_lock<std::mutex> Lock(
Mutex);
159 Cond.wait(Lock, [&] {
return Stop || !WorkStack.empty(); });
160 if (Stop && WorkStack.empty())
162 if (WorkStack.empty())
164 Task = std::move(WorkStack.back());
165 WorkStack.pop_back();
170 std::unique_lock<std::mutex> Lock(
Mutex);
171 Cond.wait(Lock, [&] {
return Stop || !WorkStack.empty(); });
174 auto Task = std::move(WorkStack.back());
175 WorkStack.pop_back();
182 std::atomic<bool> Stop{
false};
183 std::vector<std::function<void()>> WorkStack;
185 std::condition_variable
Cond;
186 std::promise<void> ThreadsCreated;
187 std::vector<std::thread> Threads;
193Executor *Executor::getDefaultExecutor() {
199 static ManagedStatic<ThreadPoolExecutor, ThreadPoolExecutor::Creator,
200 ThreadPoolExecutor::Deleter>
202 static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
209 static ThreadPoolExecutor Exec(
strategy);
217 return detail::Executor::getDefaultExecutor()->getThreadCount();
226#if LLVM_ENABLE_THREADS
228 (threadIndex == UINT_MAX)) {}
239#if LLVM_ENABLE_THREADS
242 detail::Executor::getDefaultExecutor()->add([&,
F = std::move(
F)] {
257#if LLVM_ENABLE_THREADS
259 auto NumItems = End - Begin;
262 auto TaskSize = NumItems / parallel::detail::MaxTasksPerGroup;
267 for (; Begin + TaskSize < End; Begin += TaskSize) {
269 for (
size_t I = Begin,
E = Begin + TaskSize;
I !=
E; ++
I)
275 for (
size_t I = Begin;
I != End; ++
I)
283 for (; Begin != End; ++Begin)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const SmallVectorImpl< MachineOperand > & Cond
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static cl::opt< int > ThreadCount("threads", cl::init(0))
A class to help implement exponential backoff.
LLVM_ABI bool waitForNextAttempt()
Blocks while waiting for the next attempt.
A JobSlot represents a single job slot that can be acquired from or released to a jobserver pool.
The public interface for a jobserver client.
static LLVM_ABI_FOR_TEST JobserverClient * getInstance()
Returns the singleton instance of the JobserverClient.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
This tells how a thread pool will be used.
LLVM_ABI void apply_thread_strategy(unsigned ThreadPoolNum) const
Assign the current thread to an ideal hardware CPU or NUMA node.
LLVM_ABI unsigned compute_thread_count() const
Retrieves the max available threads for the current strategy.
bool UseJobserver
If true, the thread pool will attempt to coordinate with a GNU Make jobserver, acquiring a job slot b...
An efficient, type-erasing, non-owning reference to a callable.
LLVM_ABI void spawn(std::function< void()> f)
LLVM_ABI ThreadPoolStrategy strategy
unsigned getThreadIndex()
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)