C++11线程池 和等待队列 记录

一个.h文件 从网上下的代码  

记录下 

#pragma once

#include <mutex>
#include <queue>
#include <functional>
#include <future>
#include <thread>
#include <utility>
#include <vector>

// Thread safe implementation of a Queue using a std::queue
template <typename T>

class SafeQueue
{
private:
	std::queue<T> m_queue; //利用模板函数构造队列
	std::mutex m_mutex; // 访问互斥信号量
	int max_size ;
public:
	SafeQueue() { max_size = 10; };
	SafeQueue(int size) { max_size = size; };
	SafeQueue(SafeQueue &&other) {}
	~SafeQueue() {}

	bool empty() // 返回队列是否为空
	{
		std::unique_lock<std::mutex> lock(m_mutex); // 互斥信号变量加锁,防止m_queue被改变

		return m_queue.empty();
	}

	int size()
	{
		std::unique_lock<std::mutex> lock(m_mutex); // 互斥信号变量加锁,防止m_queue被改变

		return m_queue.size();
	}

	// 队列添加元素
	bool push_data(T &t)
	{
		std::unique_lock<std::mutex> lock(m_mutex);
		if(m_queue.size() == max_size)
		{
			std::cout<<"Queue is full:"<<max_size<<std::endl;
			return false;
		}
		
		m_queue.emplace(t);
		return true;
	}

	// 队列取出元素
	bool pop_data(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;
	}
};





class BlackBox
{
private:

	class Ari // 内置线程工作类
	{
	private:
		int m_id; // 工作id
	
		BlackBox &m_pool; // 所属线程池
		
	public:
		// 构造函数
		Ari(BlackBox &_pool, const int id) :m_pool(_pool) ,m_id(id)
		{
			std::cout<<__func__<<" id:"<<m_id<<std::endl;
		}
	
	
		// 重载()操作
		void operator()()
		{
			std::function<void()> func; // 定义基础函数类func
	
			bool get_success; // 是否正在取出队列中元素
	
			while (!m_pool.m_shutdown)
			{
				{
					// 为线程环境加锁,互访问工作线程的休眠和唤醒
					std::unique_lock<std::mutex> lock(m_pool.m_conditional_mutex);
	
					// 如果任务队列为空,阻塞当前线程
					if (m_pool.m_queue.empty())
					{
						m_pool.m_conditional_lock.wait(lock); // 等待条件变量通知,开启线程
					}
	
					// 取出任务队列中的元素
					get_success = m_pool.m_queue.pop_data(func);
				}
	
				// 如果成功取出,执行工作函数
				if (get_success)
				{
					func();
				}
					
			}
		}
	};


	bool m_shutdown; // 线程池是否关闭

	SafeQueue<std::function<void()>> m_queue; // 执行函数安全队列,即任务队列

	std::vector<std::thread> m_threads; // 工作线程队列

	std::mutex m_conditional_mutex; // 线程休眠锁互斥变量

	std::condition_variable m_conditional_lock; // 线程环境锁,可以让线程处于休眠或者唤醒状态

public:
	// 线程池构造函数
	BlackBox(const int n_threads = 4)
		: m_threads(std::vector<std::thread>(n_threads)), m_shutdown(false)
	{
		std::cout<<__func__<<std::endl;
	}

	~BlackBox()
	{
		std::cout<<__func__<<std::endl;
	}
	BlackBox(const BlackBox &) = delete;

	BlackBox(BlackBox &&) = delete;

	BlackBox &operator=(const BlackBox &) = delete;

	BlackBox &operator=(BlackBox &&) = delete;

	// Inits thread pool
	void init()
	{
		for (int i = 0; i < m_threads.size(); ++i)
		{
			m_threads.at(i) = std::thread(Ari(*this, i)); // 分配工作线程
		}
	}

	int get_tasks()
	{
		return m_queue.size();
	}

	// Waits until threads finish their current task and shutdowns the pool
	void shutdown()
	{
		m_shutdown = true;
		m_conditional_lock.notify_all(); // 通知,唤醒所有工作线程

		for (int i = 0; i < m_threads.size(); ++i)
		{
			if (m_threads.at(i).joinable()) // 判断线程是否在等待
			{
				m_threads.at(i).join(); // 将线程加入到等待队列
			}
		}
	}

	// Submit a function to be executed asynchronously by the pool
	template <typename F, typename... Args>
	auto AddTask(F &&f, Args &&...args) -> std::future<decltype(f(args...))>
	{
		// Create a function with bounded parameter ready to execute
		std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...); // 连接函数和参数定义,特殊函数类型,避免左右值错误

		// Encapsulate it into a shared pointer in order to be able to copy construct
		auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);

		// Warp packaged task into void function
		std::function<void()> warpper_func = [task_ptr]()
		{
			(*task_ptr)();
		};

		// 队列通用安全封包函数,并压入安全队列
		m_queue.push_data(warpper_func);

		// 唤醒一个等待中的线程
		m_conditional_lock.notify_one();

		// 返回先前注册的任务指针
		return task_ptr->get_future();
	}
};

使用 定义

初始化

 

 使用

 for循环那里 是一个类成员函数  目前是用lambada包装了一下 

如果直接写成下面注释掉的模式 会报错   

如果直接用std::thread方式起的话 这样写是可以的 

但是 放到线程池中这么写就编译报错 目前还不清楚 原因 

关闭:

等待队列  上面线程池的已经有了 只不过不是等待队列 稍加改造 如下:


#pragma once


#include <queue>
#include <mutex>
#include <condition_variable>



template <class  			Typename >

class BlockQueue{

	public:
		 BlockQueue()
		 {
		 	m_size = 10;
			std::cout<<__func__<<" max queue size:"<<m_size <<std::endl;			
		 };
		explicit BlockQueue(int size)
		{
			m_size = size;
			std::cout<<__func__<<" max queue size:"<<m_size <<std::endl;
		}
		~BlockQueue()
		{
			std::cout<<__func__<<std::endl;			
		}

		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();
		}
		
		bool push_data(Typename &data)
		{
			std::unique_lock<std::mutex> lock(m_mutex);
			if(m_queue.size() <m_size)
			{
				m_queue.emplace(data);
				m_cond_var.notify_one();					
				return true;
			}
			return false;
		}
		
		bool	 pop_data(Typename &data)
		{
			std::unique_lock<std::mutex> lock(m_mutex);

			m_cond_var.wait(lock,[this]{
				return !this->m_queue.empty();
			});

			if(m_queue.empty())
			{
				return false;
			}
			else
			{
				data = std::move(m_queue.front());
				m_queue.pop();
				
				return true;
			}
		}

	private:

		uint32		m_size;
		std::mutex m_mutex;
		std::condition_variable m_cond_var;
		std::queue<Typename>	m_queue;
		
};




定义:

初始化:

 

使用

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QMCY_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值