1 //===- llvm/Support/Parallel.cpp - Parallel algorithms --------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/Parallel.h"
10 #include "llvm/Config/llvm-config.h"
12 #if LLVM_ENABLE_THREADS
14 #include "llvm/Support/Threading.h"
24 /// An abstract class that takes closures and runs them asynchronously.
27 virtual ~Executor() = default;
28 virtual void add(std::function
<void()> func
) = 0;
30 static Executor
*getDefaultExecutor();
34 /// An Executor that runs tasks via ConcRT.
35 class ConcRTExecutor
: public Executor
{
37 Taskish(std::function
<void()> Task
) : Task(Task
) {}
39 std::function
<void()> Task
;
41 static void run(void *P
) {
42 Taskish
*Self
= static_cast<Taskish
*>(P
);
44 concurrency::Free(Self
);
49 virtual void add(std::function
<void()> F
) {
50 Concurrency::CurrentScheduler::ScheduleTask(
51 Taskish::run
, new (concurrency::Alloc(sizeof(Taskish
))) Taskish(F
));
55 Executor
*Executor::getDefaultExecutor() {
56 static ConcRTExecutor exec
;
61 /// An implementation of an Executor that runs closures on a thread pool
63 class ThreadPoolExecutor
: public Executor
{
65 explicit ThreadPoolExecutor(unsigned ThreadCount
= hardware_concurrency())
67 // Spawn all but one of the threads in another thread as spawning threads
69 std::thread([&, ThreadCount
] {
70 for (size_t i
= 1; i
< ThreadCount
; ++i
) {
71 std::thread([=] { work(); }).detach();
77 ~ThreadPoolExecutor() override
{
78 std::unique_lock
<std::mutex
> Lock(Mutex
);
85 void add(std::function
<void()> F
) override
{
86 std::unique_lock
<std::mutex
> Lock(Mutex
);
95 std::unique_lock
<std::mutex
> Lock(Mutex
);
96 Cond
.wait(Lock
, [&] { return Stop
|| !WorkStack
.empty(); });
99 auto Task
= WorkStack
.top();
107 std::atomic
<bool> Stop
{false};
108 std::stack
<std::function
<void()>> WorkStack
;
110 std::condition_variable Cond
;
111 parallel::detail::Latch Done
;
114 Executor
*Executor::getDefaultExecutor() {
115 static ThreadPoolExecutor exec
;
121 void parallel::detail::TaskGroup::spawn(std::function
<void()> F
) {
123 Executor::getDefaultExecutor()->add([&, F
] {
128 #endif // LLVM_ENABLE_THREADS