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();
95 ~ThreadPoolExecutor()
override {
97 std::thread::id CurrentThreadId = std::this_thread::get_id();
98 for (std::thread &
T : Threads)
99 if (
T.get_id() == CurrentThreadId)
106 static void *call() {
return new ThreadPoolExecutor(
strategy); }
109 static void call(
void *
Ptr) { ((ThreadPoolExecutor *)
Ptr)->stop(); }
112 void add(std::function<
void()>
F)
override {
114 std::lock_guard<std::mutex> Lock(
Mutex);
115 WorkStack.push_back(std::move(
F));
124 threadIndex = ThreadID;
132 static thread_local std::unique_ptr<ExponentialBackoff> Backoff;
150 Slot = TheJobserver->tryAcquire();
156 [&] { TheJobserver->release(std::move(Slot)); });
159 std::function<void()> Task;
161 std::unique_lock<std::mutex> Lock(
Mutex);
162 Cond.wait(Lock, [&] {
return Stop || !WorkStack.empty(); });
163 if (Stop && WorkStack.empty())
165 if (WorkStack.empty())
167 Task = std::move(WorkStack.back());
168 WorkStack.pop_back();
173 std::unique_lock<std::mutex> Lock(
Mutex);
174 Cond.wait(Lock, [&] {
return Stop || !WorkStack.empty(); });
177 auto Task = std::move(WorkStack.back());
178 WorkStack.pop_back();
185 std::atomic<bool> Stop{
false};
186 std::vector<std::function<void()>> WorkStack;
188 std::condition_variable
Cond;
189 std::promise<void> ThreadsCreated;
190 std::vector<std::thread> Threads;
198static Executor *TheExec =
nullptr;
199static std::once_flag Flag;
205void createExecutor() {
225 static ManagedStatic<ThreadPoolExecutor, ThreadPoolExecutor::Creator,
226 ThreadPoolExecutor::Deleter>
228 static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
229 TheExec = Exec.get();
235 static ThreadPoolExecutor Exec(
strategy);
240Executor *Executor::getDefaultExecutor() {
242 std::call_once(Flag, createExecutor);
249 return detail::Executor::getDefaultExecutor()->getThreadCount();
258#if LLVM_ENABLE_THREADS
260 (threadIndex == UINT_MAX)) {}
271#if LLVM_ENABLE_THREADS
274 detail::Executor::getDefaultExecutor()->add([&,
F = std::move(
F)] {
289#if LLVM_ENABLE_THREADS
291 auto NumItems = End - Begin;
294 auto TaskSize = NumItems / parallel::detail::MaxTasksPerGroup;
299 for (; Begin + TaskSize < End; Begin += TaskSize) {
301 for (
size_t I = Begin,
E = Begin + TaskSize;
I !=
E; ++
I)
307 for (
size_t I = Begin;
I != End; ++
I)
315 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 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.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
LLVM_ABI void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)