发现 zeromq 的 yqueue_t 模板类,其数据存储理念设计得非常妙。借这一理念,按照 STL 的泛型类 queue 的接口标准,我设计了一个线程安全的 单生产者/单消费者(单线程push/单线程pop) FIFO 队列,以此满足更为广泛的应用。
1. 数据存储理念的结构图
- 队列的整体结构上,使用链表的方式,将多个固定长度的 chunk 串联起来;
- 每个 chunk 则可用于存储队列所需要的元素;
- 增加一个可交换的 chunk 单元,利于内存复用;
- 队列使用时,支持 单个线程的 push(生产) 和 单个线程 pop(消费)的并发操作(内部并未加锁)。
2. 源码 (xspsc_queue.h)
/**
* @file xspsc_queue.h
* <pre>
* Copyright (c) 2018, Gaaagaa All rights reserved.
*
* 文件名称:xspsc_queue.h
* 创建日期:2018年12月17日
* 文件标识:
* 文件摘要:实现线程安全的 单生产者/单消费者(single producer/single consumer) FIFO 队列。
*
* 特别声明:x_spsc_queue_t 的设计,主要参考了 zeromq 的 yqueue_t 模板类的数据存储理念。
* 特别鸣谢:zeromq 开源项目,Lee哥 。
*
* 当前版本:1.0.0.0
* 作 者:
* 完成日期:2018年12月17日
* 版本摘要:
*
* 历史版本:
* 原作者 :
* 完成日期:
* 版本摘要:
* </pre>
*/
#ifndef __XSPSC_QUEUE_H__
#define __XSPSC_QUEUE_H__
#include <memory>
#include <atomic>
#ifndef ENABLE_XASSERT
#if ((defined _DEBUG) || (defined DEBUG))
#define ENABLE_XASSERT 1
#else // !((defined _DEBUG) || (defined DEBUG))
#define ENABLE_XASSERT 0
#endif // ((defined _DEBUG) || (defined DEBUG))
#endif // ENABLE_XASSERT
#ifndef XASSERT
#if ENABLE_XASSERT
#include <cassert>
#define XASSERT(xptr) assert(xptr)
#else // !ENABLE_XASSERT
#define XASSERT(xptr)
#endif // ENABLE_XASSERT
#endif // XASSERT
// x_spsc_queue_t
/**
* @class x_spsc_queue_t
* @brief 实现线程安全的 单生产者/单消费者(single producer/single consumer) FIFO 队列。
*
* @param [in ] _Ty : 队列存储的元素类型。
* @param [in ] _En : 队列中的存储块可容纳元素的数量。
* @param [in ] _Alloc : 元素分配器。
*/
template< typename _Ty, size_t _En, typename _Alloc = std::allocator< _Ty > >
class x_spsc_queue_t : protected _Alloc
{
static_assert(_En >= 4, "_En size value must be greater than or equal to 4!");
// common data types
public:
using x_element_t = _Ty;
private:
/**
* @struct x_chunk_t