c++双队列

185 阅读1分钟

背景

平时在做一些数据处理中,会遇到一个读线程,一个写线程的情形,为了方便使用,可以简单封装一下线程安全的队列。

线程安全的队列

#ifndef double_deque_h__
#define double_deque_h__

#include <deque>
#include <mutex>

template<typename val_type>
class utils_deque
{
public:
	utils_deque() {}
	~utils_deque() 
	{ 
		std::lock_guard<std::mutex> locker(m_mutex);

		while (!m_deque.empty())
		{
			val_type* var = m_deque.front();
			if (var)
			{
				delete var;
				var = NULL;
			}
			m_deque.pop_front();
		}
	}

	void push(val_type *var)
	{
		std::lock_guard<std::mutex> locker(m_mutex);

		m_deque.push_back(var);
	}

	val_type *pop()
	{
		std::lock_guard<std::mutex> locker(m_mutex);

		if (m_deque.empty())
		{
			return nullptr;
		}
		else
		{
			val_type* var = m_deque.front();
			m_deque.pop_front();
			return var;
		}
	}

	size_t size()
	{
		return m_deque.size();
	}

private:
	std::mutex m_mutex;
	std::deque<val_type* > m_deque;
};
#endif // double_deque_h__

为了方便自动释放空间,设计只支持传入指针对象。

双队列

但平时实际运用中,可能的需求是一个队列用于读,一个队列用于写;读队列用完之后会放入写队列;为了简化外部使用和自动管理,可以使用模版双队列。

#ifndef double_deque_h__
#define double_deque_h__

#include <deque>
#include <mutex>

template<typename val_type>
class utils_deque_rw
{
public:
	utils_deque_rw(utils_deque<val_type> *read, utils_deque<val_type> *write)
		: m_pop(read)
		, m_push(write)
		, m_var(NULL)
	{
		if (m_pop)
		{
			m_var = m_pop->pop();
		}
	}

	~utils_deque_rw()
	{
		if (m_push && m_var)
		{
			m_push->push(m_var);
		}
	}

	val_type* get()
	{
		return m_var;
	}

	//获取双队列总大小
	int size()
	{
		if (m_pop && m_push)
		{
			if (m_var)
			{
				return m_pop->size() + m_push->size() + 1;
			}
			else
			{
				return m_pop->size() + m_push->size();
			}
		}
		else
		{
			return -1;
		}
	}

	//重载-> 方便可以直接访问对象数据
	val_type* operator->()
	{
		return m_var;
	}

	//重载A a;中if(a)
	typedef void(*unspecified_bool_type)();
	static void unspecified_bool_true() {}
	operator unspecified_bool_type() const
	{
		return m_var == NULL ? 0 : unspecified_bool_true;
	}

	//重载A a;中if(!a)
	bool operator!() const
	{
		return m_var == NULL;
	}

private:
	utils_deque<val_type> *m_pop;   //出队列,需要读取的数据队列
	utils_deque<val_type> *m_push;  //入队列,数据用完之后放入的空闲队列

	val_type* m_var;//获取到的对象数据
};

#endif // double_deque_h__

使用示例

定义

#define CACHE_SIZE 10

struct data
{

}

utils_deque<data> m_used;
utils_deque<data> m_idle;

初始化

for (size_t i = 0; i < CACHE_SIZE; ++i)
{
    data *var = new data();
    m_idle.push(var);
}

读写

utils_deque_rw<data> rw(&m_idle, &m_used);
if (!rw)
{
  //do something
}
else
{
  //do something
}