10#include "llvm/Config/llvm-config.h"
24#if LLVM_ENABLE_THREADS
27static thread_local unsigned threadIndex;
31thread_local unsigned threadIndex;
41 virtual ~Executor() =
default;
42 virtual void add(std::function<
void()> func) = 0;
44 static Executor *getDefaultExecutor();
49class ThreadPoolExecutor :
public Executor {
52 unsigned ThreadCount = S.compute_thread_count();
55 Threads.reserve(ThreadCount);
57 std::lock_guard<std::mutex> Lock(
Mutex);
60 auto &Thread0 = Threads[0];
61 Thread0 = std::thread([
this, ThreadCount, S] {
62 for (
unsigned I = 1;
I < ThreadCount; ++
I) {
63 Threads.emplace_back([=] { work(S,
I); });
67 ThreadsCreated.set_value();
74 std::lock_guard<std::mutex> Lock(
Mutex);
80 ThreadsCreated.get_future().wait();
83 ~ThreadPoolExecutor()
override {
85 std::thread::id CurrentThreadId = std::this_thread::get_id();
86 for (std::thread &
T : Threads)
87 if (
T.get_id() == CurrentThreadId)
94 static void *call() {
return new ThreadPoolExecutor(
strategy); }
97 static void call(
void *
Ptr) { ((ThreadPoolExecutor *)
Ptr)->stop(); }
100 void add(std::function<
void()>
F)
override {
102 std::lock_guard<std::mutex> Lock(
Mutex);
103 WorkStack.push(std::move(
F));
110 threadIndex = ThreadID;
113 std::unique_lock<std::mutex> Lock(
Mutex);
114 Cond.wait(Lock, [&] {
return Stop || !WorkStack.empty(); });
117 auto Task = std::move(WorkStack.top());
124 std::atomic<bool> Stop{
false};
125 std::stack<std::function<void()>> WorkStack;
127 std::condition_variable
Cond;
128 std::promise<void> ThreadsCreated;
129 std::vector<std::thread> Threads;
132Executor *Executor::getDefaultExecutor() {
151 static ManagedStatic<ThreadPoolExecutor, ThreadPoolExecutor::Creator,
152 ThreadPoolExecutor::Deleter>
154 static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
176#if LLVM_ENABLE_THREADS
179 detail::Executor::getDefaultExecutor()->add([&,
F = std::move(
F)] {
204#if LLVM_ENABLE_THREADS
205 auto NumItems = End - Begin;
206 if (NumItems > 1 && parallel::strategy.ThreadsRequested != 1) {
209 auto TaskSize = NumItems / parallel::detail::MaxTasksPerGroup;
214 for (; Begin + TaskSize < End; Begin += TaskSize) {
216 for (
size_t I = Begin,
E = Begin + TaskSize;
I !=
E; ++
I)
222 for (
size_t I = Begin;
I != End; ++
I)
230 for (; Begin != End; ++Begin)
SmallVector< MachineOperand, 4 > Cond
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
This tells how a thread pool will be used.
void apply_thread_strategy(unsigned ThreadPoolNum) const
Assign the current thread to an ideal hardware CPU or NUMA node.
An efficient, type-erasing, non-owning reference to a callable.
void execute(std::function< void()> f)
void spawn(std::function< void()> f)
static std::atomic< int > TaskGroupInstances
ThreadPoolStrategy strategy
unsigned getThreadIndex()
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)