简介
最近学习C++11 的thread并发编程,但是里面的内容还不是很全面,线程池和一些信号量也没有,之前的笔记linux网络编程学习笔记——线程池是基于纯c的linux版本的,想着基于C++11 thread 和其新特性做一个类似的线程池组件以便于学习,大部分借鉴github上一个threadpool,只是这个没有线程池管理,无法根据情况自动扩容和缩减线程数量,进行了二次修改。
关于线程池的原理网上一大把就不详细说明了,直接上源码。
SafeQueue.h
#include <mutex>
#include <queue>
// Thread safe implementation of a Queue using an std::queue
template <typename T>
class SafeQueue {
private:
std::queue<T> m_queue;
std::mutex m_mutex;
public:
SafeQueue() {
}
SafeQueue(SafeQueue& other) {
//TODO:
}
~SafeQueue() {
}
bool empty() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.empty();
}
int size() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.size();
}
void enqueue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.push(t);
}
bool dequeue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_queue.empty()) {
return false;
}
t = std::move(m_queue.front());
m_queue.pop();
return true;
}
};
这部分代码没什么好说的,就是对一个队列进行了二次封装的模板类保证线程安全用于存放任务队列。
ThreadPool.h
#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>
#include <chrono>
#include "SafeQueue.h"
class ThreadPool {
private:
class ThreadWorker {
private:
int m_id;
ThreadPool * m_pool;
public:
ThreadWorker(ThreadPool * pool, const int id)
: m_pool(pool), m_id(id) {
}
void operator()() {
std::function<void()> func;
bool dequeued;
while (!m_pool->m_shutdown) {
{
std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
while (m_pool->m_queue.empty() && !m_pool->m_shutdown)
{
if (m_pool->wait_exit_thr_num > 0)
{
m_pool->wait_exit_thr_num--;
if (m_pool->live_thr_num > m_pool->min_thr_num)
{
m_pool->live_thr_num--;
return;
}
}
else
{
m_pool->m_conditional_lock.wait(lock);
}
}
}
dequeued = m_pool->m_queue.dequeue(func);
if (dequeued) {
m_pool->busy_thr_num++;
func();
m_pool->busy_thr_num--;
}
}
}
};
//
void adjust_thread(void)
{
while (!m_shutdown)
{
std::this_thread::sleep_for(period);
std::unique_lock<std::mutex> lock(m_conditional_mutex);
int queue_size = m_queue.size();
int live_thr_num = this->live_thr_num;
lock.unlock();
int busy_thr_num = this->busy_thr_num;
if (queue_size >= min_wait_task_num && live_thr_num < max_thr_num) {
lock.lock();
int add = 0;
for (int i = 0; i < max_thr_num && add < default_thread_vary
&& live_thr_num < max_thr_num; i++) {
if (m_threads[i].get_id() == std::thread::id(