SPSCQueue C++实现

前言

        SPSCQueue(Single Producer Single Consumer Queue,单生产者单消费者队列)是一个单生产者单消费者的线程安全队列,适应于一个线程生产(PUSH)、一个线程消费(POP),相对于多个生产者、多个消费者的队列实现更简单。

实现原理

        1、使用环形缓冲数组来保存数据,申明头指针、尾指针来标识PUSH\POP操作的位置

        2、使用C++原子锁来保证线程安全(而非进程锁,避免多线程访问时的竞态条件)

代码实现


#include <cstdint>
#include <atomic>

//----------------------------------------------------------------
// 适用于单个生产者单个消费者
// 注:单个生产者,多个消费者也可以使用,但是消费者pop不是必成功
//----------------------------------------------------------------

template<typename T, int32_t N>
class ScspQueue
{
public:
	void	clear();

	bool	empty();
	bool	full();

	int32_t size();

	bool	push(const T&);
	bool	pop(T&);

private:
	int32_t				m_readIndex = 0;
	int32_t				m_writeIndex = 0;
	std::atomic_bool	m_readLock = 0;
	std::atomic_bool	m_writeLock = 0;
	T					m_aData[N + 1];
};

template<typename T, int32_t N>
void ScspQueue<T, N>::clear()
{
	bool expected = true;
	while (m_readLock.compare_exchange_strong(expected, false));

	expected = true;
	while (m_writeLock.compare_exchange_strong(expected, false));

	m_readIndex = m_writeIndex = 0;

	m_readIndex = 0;
	m_writeIndex = 0;
}

template<typename T, int32_t N>
bool ScspQueue<T, N>::empty()
{
	return size() == 0;
}

template<typename T, int32_t N>
bool ScspQueue<T, N>::full()
{
	return size() == N;
}

template<typename T, int32_t N>
int32_t ScspQueue<T, N>::size()
{
	return (m_writeIndex - m_readIndex + N + 1) % (N + 1);
}

template<typename T, int32_t N>
bool ScspQueue<T, N>::push(const T& data)
{
	if (full()){
		return false;
	}

	memcpy(&m_aData[m_writeIndex], &data, sizeof(T));

	bool expected = true;
	if (!m_writeLock.compare_exchange_strong(expected, false)) {
		return false;
	}

	m_writeIndex = (m_writeIndex + +1 + N + 1) % (N + 1);
	m_writeLock = false;

	return true;
}

template<typename T, int32_t N>
bool ScspQueue<T, N>::pop(T& data)
{
	if (empty()){
		return false;
	}

	memcpy(&data, &m_aData[m_readIndex], sizeof(T));

	bool expected = true;
	if (!m_readLock.compare_exchange_strong(expected, false)) {
		return false;
	}

	m_readIndex = (m_readIndex + 1 + N + 1) % (N + 1);
	m_readIndex = 0;

	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值