Skip to content

Instantly share code, notes, and snippets.

@Darianopolis
Last active April 28, 2024 01:57
Show Gist options
  • Save Darianopolis/fe0739c9a67ffe7d5d377aa229fece57 to your computer and use it in GitHub Desktop.
Save Darianopolis/fe0739c9a67ffe7d5d377aa229fece57 to your computer and use it in GitHub Desktop.
Minimalistic C++ thread pool implementation
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
class ThreadPool
{
std::vector<std::jthread> workers;
std::deque<std::move_only_function<void()>> queue;
std::mutex mutex;
std::condition_variable cv;
bool stop = false;
public:
ThreadPool(uint32_t threads)
{
for (uint32_t i = 0 ; i < threads; ++i) {
workers.emplace_back([this] {
for(;;) {
std::move_only_function<void()> task;
{
std::unique_lock lock{mutex};
cv.wait(lock, [&]{ return stop || !queue.empty(); });
if(stop && queue.empty()) {
return;
}
task = std::move(queue.front());
queue.pop_front();
}
task();
}
});
}
}
~ThreadPool()
{
{
std::scoped_lock lock{mutex};
stop = true;
}
cv.notify_all();
workers.clear();
}
template<class Fn, class... Args>
auto enqueue(Fn&& f, Args&&... args)
{
auto task = std::packaged_task(
[f = std::forward<Fn>(f), ...args = std::forward<Args>(args)] {
return f(std::forward<Args>(args)...);
});
auto res = task.get_future();
{
std::scoped_lock lock{mutex};
queue.push_back([task = std::move(task)]() mutable { task(); });
}
cv.notify_one();
return res;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment