前言:
简单来说,共享内存不能自动扩展,申请多少就是多少,而且只能用C++内置的数据类型。
也不能用STL容器,例如vector会自动扩展,容易造成内存泄漏,越界等问题。移动语义也不能用。要想实现多进程的生产/消费者模型只能采用循环队列。
循环队列类
值得一提的是这里面头尾指针的移动算法:(指针+1)取最大长度的余数。其他都很简单。
#include<iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;
template<typename TT,int Maxlength>
class squeue
{
private:
bool m_inited;//队列被初始化标志,true——初始化成功,false——未被初始化
TT m_data[Maxlength];//用数存储循环队列的元素
int m_head;//队列头指针
int m_tail;//队列尾指针
int m_length;//队列实际长度
squeue(const squeue&)=delete;//禁用拷贝构造函数
squeue operator=(const squeue&)=delete;//禁用赋值函数
public:
squeue(){init();};//构造函数
// 循环队列的初始化 用于共享内存的队列不能调用构造函数,必须调用此函数初始化
void init(){//循环队列的初始化只能执行一次
if(m_inited!=true){
m_head=0;//头指针指向第一个元素
m_tail=Maxlength-1;//尾指针指向队列最后一个元素
m_length=0;//实际长度
memset(m_data,0,sizeof(m_data));//清空数组
m_inited=true;
}
}
//元素入队 返回值true——成功 false——失败
bool push(const TT &ee){
if(m_length==Maxlength){
cout<<"循环队列已满,入队失败。\n";return false;
}
//先移动尾指针,再拷贝数据
m_tail=(m_tail+1)%Maxlength;//尾指针移动
m_data[m_tail]=ee;
m_length++;
return true;
}
//循环队列长度 返回长度的值
int size(){
return m_length;
}
//判断循环队列是否为空 true——空 false——非空
bool Is_empty(){
if(m_length==0)return true;
return false;
}
//判断循环队列是否已满 true——满 false——不满
bool Is_full(){
if(m_length==Maxlength)return true;
return false;
}
//查看队头元素,只读
const TT& front(){
return m_data[m_head];
}
//查看队尾元素,只读
const TT& back(){
return m_data[m_tail];
}
//元素出队 true——成功 false——失败
bool pop(){
if(Is_full()==true)return false;
m_head=(m_head+1)%Maxlength;
m_length--;
return true;
}
//显示循环队列的全部元素,做为临时调试使用,只有当队列元素支持cout输出时才可用
void printsqueue(){
for(int ii{};ii<size();ii++){
cout<<"m_data["<<(m_head+ii)%Maxlength<<"]="
<<m_data[(m_head+ii)%Maxlength]<<endl;
}
}
};
整一个测试程序demo01:
#include"public.cpp"
int main()
{
using ElemType=int;
squeue