CThreadPool.h
#pragma once
#include <functional>
#include <future>
#include <iostream>
#include <queue>
#include <vector>
#include <thread>
#include <atomic>
#include <mutex>
#include <condition_variable>
class CThreadPool
{
using Task = std::function<void()>;
public:
CThreadPool(size_t size);
~CThreadPool();
template <typename F, typename ...Args>
auto mAddTask(F&& f, Args && ...args) -> std::future<decltype(f(args...))>;
void mWork();
private:
std::vector<std::thread> mThreadPools;
std::queue<Task> mTasks;
std::mutex mLock;
std::condition_variable mCVTask;
std::atomic<bool> mExit;
};
void test();
CThreadPool.cpp
#include "CThreadPool.h"
CThreadPool::CThreadPool(size_t size) : mExit(false)
{
size = (size <= 0) ? 1 : size;
for (size_t i = 0; i < size; ++i) {
mThreadPools.emplace_back(std::move(std::thread(&CThreadPool::mWork, this)));
}
}
CThreadPool::~CThreadPool()
{
mExit.store(true);
mCVTask.notify_all();
for (std::thread& thread : mThreadPools) {
thread.join();
}
}
template <typename F, typename ...Args>
auto CThreadPool::mAddTask(F&& f, Args && ...args) -> std::future<decltype(f(args...))>
{
using ret_type = decltype(f(args...));
auto task_func = std::make_shared<std::packaged_task<ret_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
{
std::unique_lock<std::mutex> uq_lock(mLock);
mTasks.emplace([task_func]() { (*task_func)(); });
}
mCVTask.notify_one();
return task_func->get_future();
}
void CThreadPool::mWork()
{
while (1) {
std::unique_lock<std::mutex> uq_lock(mLock);
mCVTask.wait(uq_lock, [this]() { return !mTasks.empty() || mExit.load();});
if (mExit.load()) {
return;
}
Task task(std::move(mTasks.front()));
mTasks.pop();
task();
}
}
int Task1(int)
{
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task1 start..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task1 end..." << std::endl;
return 24;
}
class Task2
{
public:
int operator()(int, int) {
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task2 start..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task2 end..." << std::endl;
return 24;
}
};
void test()
{
std::cout << "Main Thread ID : " << std::this_thread::get_id() << ", start..." << std::endl;
CThreadPool thread_pool(5);
std::future<int> f_task1 = thread_pool.mAddTask(Task1, 1);
std::future<int> f_task2 = thread_pool.mAddTask(Task2(), 1, 1);
std::future<int> f_task3 = thread_pool.mAddTask([]() {
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task3 start..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Thread ID : " << std::this_thread::get_id() << ", Task3 end..." << std::endl;
return 8;
});
std::cout << "Task1 return value : " << f_task1.get() << std::endl;
std::cout << "Task2 return value : " << f_task2.get() << std::endl;
std::cout << "Task3 return value : " << f_task3.get() << std::endl;
std::cout << "Main Thread ID : " << std::this_thread::get_id() << ", end..." << std::endl;
}