代码主要是做练习用的,水平有限,路过的大神看到代码有哪里不好的请帮忙指出来,万分感谢。
#pragma once
#include <mutex>
#include <vector>
#include <queue>
#include <thread>
#include <future>
#include <atomic>
#include <functional>
#include <stdexcept>
#include <condition_variable>
class ThreadPool
{
public:
using Task = std::function<void()>;
ThreadPool()
{}
~ThreadPool()
{
mbRunning.store(false);
moCondVar.notify_all();
for (auto th = mvecThreads.begin(); th != mvecThreads.end(); th++)
{
if ((*th).joinable())
{
(*th).join();
}
}
}
void mvInit(int iSize)
{
mbRunning.store(true);
miThreadSize = iSize;
for (int i = 0; i < iSize; i++)
{
mvecThreads.emplace_back(
[this]
{
while (mbRunning.load())
{
Task task;
{
std::unique_lock<std::mutex> lock(moMutex);
moCondVar.wait(lock, [this] {return !mbRunning.load() || !mqueTasks.empty(); });
if (!mbRunning.load())
{
break;
}
task = mqueTasks.front();
mqueTasks.pop();
}
task();
}
});
}
}
template<typename F, typename... Args>
decltype(auto) mAddTask(F&& f, Args&&... args)
{
if (!mbRunning.load())
{
//error
throw std::runtime_error("ThreadPool::mAddTask add task on threadpool stoped!");
}
//using return_type = typename std::result_of_t<F(Args...)>;
using return_type = decltype(f(args...));
// 这里不知道为啥要用指针,我开始是写的下面注释掉那段代码,老报错,
// 还没搞清楚问题在哪,求路过的大神指教
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(moMutex);
mqueTasks.emplace([task] {(*task)(); });
}
//using return_type = decltype(f(args...));
//auto task = std::packaged_task<return_type()>(std::bind(std::forward<F>(f)), std::forward<Args>(args)...);
//std::future<return_type> res = task.get_future();
//{
// std::unique_lock<std::mutex> lock(moMutex);
// mqueTasks.emplace([task] {(task)(); });
//}
moCondVar.notify_one();
return res;
}
private:
ThreadPool(const ThreadPool&) = delete;
ThreadPool(ThreadPool&&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
private:
int miThreadSize = 0;
std::vector<std::thread> mvecThreads;
std::queue<Task > mqueTasks;
std::mutex moMutex;
std::condition_variable moCondVar;
std::atomic<bool> mbRunning{ false };
};
int fun1(int a, int b)
{
std::cout << "run fun1" << std::endl;
return a + b;
}
std::string fun2()
{
std::cout << "run fun2" << std::endl;
return std::move("hello");
}
void test()
{
ThreadPool pool;
pool.mvInit(5);
auto res1 = pool.mAddTask(fun1, 2, 3);
auto res2 = pool.mAddTask(fun2);
auto res3 = pool.mAddTask([] {std::cout << "run fun3" << std::endl; });
int r1 = res1.get();
std::string s1 = res2.get();
std::cout << "fun1=" << r1 << std::endl;
std::cout << "fun2=" << s1 << std::endl;
}