Skip to content

Instantly share code, notes, and snippets.

@kerrytazi
Created July 24, 2025 04:16
Show Gist options
  • Select an option

  • Save kerrytazi/5e5041a23e41540538976139e512f3e9 to your computer and use it in GitHub Desktop.

Select an option

Save kerrytazi/5e5041a23e41540538976139e512f3e9 to your computer and use it in GitHub Desktop.
Simple thread pool implementation
#pragma once
#include <vector>
#include <functional>
#include <thread>
#include <mutex>
#include <condition_variable>
class ThreadPool
{
public:
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool(ThreadPool&&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
ThreadPool(unsigned int thread_count)
{
if (thread_count == 0)
thread_count = 1;
threads_.reserve(thread_count);
tasks_.reserve(thread_count * 16);
for (unsigned int i = 0; i < thread_count; ++i)
{
threads_.emplace_back([this]()
{
while (true)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lck(mtx_);
cv_.wait(lck, [&]() { return !tasks_.empty() || destroy_; });
if (tasks_.empty() && destroy_)
return;
task = std::move(tasks_.back());
tasks_.pop_back();
}
task();
}
});
}
}
ThreadPool()
: ThreadPool(std::thread::hardware_concurrency())
{
}
~ThreadPool()
{
{
std::unique_lock<std::mutex> lck(mtx_);
destroy_ = true;
}
cv_.notify_all();
for (auto& th : threads_)
th.join();
}
void add(std::function<void()>&& task)
{
{
std::unique_lock<std::mutex> lck(mtx_);
tasks_.insert(tasks_.begin(), std::move(task));
}
cv_.notify_one();
}
void add(std::vector<std::function<void()>>&& tasks)
{
auto size = tasks.size();
{
std::unique_lock<std::mutex> lck(mtx_);
tasks_.reserve(tasks_.size() + tasks.size());
tasks_.insert(
tasks_.end(),
std::make_move_iterator(tasks.begin()),
std::make_move_iterator(tasks.end())
);
}
if (size > 1)
cv_.notify_all();
else
cv_.notify_one();
}
private:
std::mutex mtx_;
std::condition_variable cv_;
bool destroy_ = false;
std::vector<std::function<void()>> tasks_;
std::vector<std::thread> threads_;
};
#include "ThreadPool.hpp"
#include <iostream>
#include <atomic>
int main()
{
// int counter = 0; // Data race example
std::atomic<int> counter = 0;
{
ThreadPool tp;
std::vector<std::function<void()>> tasks;
for (int i = 0; i < 10000; ++i)
{
tasks.push_back([&]() { ++counter; });
tasks.push_back([&]() { --counter; });
}
tp.add(std::move(tasks));
}
std::cout << "counter: " << counter << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment