forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Release Commit @ 0b96bd5
This commit is contained in:
81
iqpilot/tools/cabana/ui/threadpool.h
Normal file
81
iqpilot/tools/cabana/ui/threadpool.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
class ThreadPool {
|
||||
public:
|
||||
static ThreadPool &instance() {
|
||||
static ThreadPool pool(std::clamp(std::thread::hardware_concurrency(), 2u, 4u));
|
||||
return pool;
|
||||
}
|
||||
|
||||
std::future<void> run(std::function<void()> fn) {
|
||||
auto task = std::make_shared<std::packaged_task<void()>>(std::move(fn));
|
||||
std::future<void> future = task->get_future();
|
||||
{
|
||||
std::lock_guard lk(mutex_);
|
||||
tasks_.push([task]() { (*task)(); });
|
||||
}
|
||||
cv_.notify_one();
|
||||
return future;
|
||||
}
|
||||
|
||||
~ThreadPool() {
|
||||
{
|
||||
std::lock_guard lk(mutex_);
|
||||
stop_ = true;
|
||||
}
|
||||
cv_.notify_all();
|
||||
for (auto &t : threads_) t.join();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit ThreadPool(unsigned n) {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
threads_.emplace_back([this]() {
|
||||
for (;;) {
|
||||
std::function<void()> task;
|
||||
{
|
||||
std::unique_lock lk(mutex_);
|
||||
cv_.wait(lk, [this]() { return stop_ || !tasks_.empty(); });
|
||||
if (stop_ && tasks_.empty()) return;
|
||||
task = std::move(tasks_.front());
|
||||
tasks_.pop();
|
||||
}
|
||||
task();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::thread> threads_;
|
||||
std::queue<std::function<void()>> tasks_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
bool stop_ = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline void parallelFor(size_t n, const std::function<void(size_t begin, size_t end)> &fn) {
|
||||
const size_t chunks = std::clamp<size_t>(std::thread::hardware_concurrency(), 2, 4) + 1;
|
||||
const size_t chunk = (n + chunks - 1) / chunks;
|
||||
if (chunk == 0) return;
|
||||
std::vector<std::future<void>> futures;
|
||||
size_t begin = chunk;
|
||||
for (; begin < n; begin += chunk) {
|
||||
futures.push_back(ThreadPool::instance().run([&fn, begin, end = std::min(begin + chunk, n)]() { fn(begin, end); }));
|
||||
}
|
||||
fn(0, std::min(chunk, n));
|
||||
for (auto &f : futures) f.get();
|
||||
}
|
||||
Reference in New Issue
Block a user