工作之余写的一个简单的循环队列模板类。为什么要用循环队列呢? 因为它省去了元素拷贝的开销,众所周知,拷贝元素是很耗时,会比较影响效率,
特别是大规模的拷贝,更是如此。相比较直队列,循环队列不需要在头部元素被取出时,需要将后面的元素向头部移动的操作,因此可以说省时省力,
对效率而言,也是个比较大的提升~~
共有4个程序文件: common_type.h common_struct.h common_queue.h main.cpp
外加一个编译用的文件: Makefile
//file: common_struct.h
/*********************************************
* filename: common_struct.h
* date: 2014-07-23 10:24
* author: jackie
* desc: define struct used in program
*********************************************/
#ifndef COMMON_STRUCT_H
#define COMMON_STRUCT_H
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "common_type.h"
typedef struct STC_LOG
{
std::string time;
std::string content;
uint32_t level;
STC_LOG& operator=(const STC_LOG& obj)
{
this->time = obj.time;
this->content = obj.content;
this->level = obj.level;
return *this;
}
STC_LOG()
{
time.clear();
content.clear();
level = 0;
}
~STC_LOG()
{
time.clear();
content.clear();
level = 0;
}
void show()
{
printf("loginfo time=%s, content=%s, level=%d\n", time.c_str(), content.c_str(), level);
}
}STC_LOG;
#endif
//file: common_type.h
/***********************************************************
* filename: common_type.h
* date: 2014-07-23 10:28
* author: jackie
* desc: define data type which is more convenient to use
***********************************************************/
#ifndef COMMON_TYPE_H
#define COMMON_TYPE_H
typedef int int32_t;
typedef unsigned int uint32_t;
#endif
//file: common_queue.h
/************************************************************
** filename: common_queue.h
** date: 2014-07-22 22:32
** author: jackie
** desc: 实现一个循环队列模板
************************************************************/
#ifndef BASE_CIRCLE_QUEUE_T_H
#define BASE_CIRCLE_QUEUE_T_H
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include "common_type.h"
static const uint32_t min_free_size = 2;
template<typename T, uint32_t SIZE>
class CCommonQueue_T
{
public:
CCommonQueue_T()
{
printf("begin constructor\n");
Init(SIZE);
printf("end constructor\n");
}
virtual ~CCommonQueue_T()
{
printf("begin deconstruct\n");
if(m_arrBuf)
{
delete []m_arrBuf;
}
m_uHead = 0;
m_uTail = 0;
m_uMaxBufLen = 0;
printf("end deconstruct\n");
}
void Init(const uint32_t size)
{
m_uMaxBufLen = size;
m_arrBuf = new T[m_uMaxBufLen];
m_uHead = 0;
m_uTail = 0;
for(uint32_t i=0; i<m_uMaxBufLen; i++)
{
m_vecMark.push_back(0);
}
}
bool Empty()
{
if( m_uHead == m_uTail)
{
return true;
}
return false;
}
bool Full()
{
uint32_t left = 0;
if( m_uTail >= m_uHead )
{
left = m_uMaxBufLen - ( m_uTail - m_uHead );
}
if( m_uTail < m_uHead )
{
left = m_uHead - m_uTail;
}
//留8个位置空闲【防止追尾情况】
if( left <= min_free_size )
{
return true;
}
return false;
}
//向队列中添加一个元素
uint32_t Push(const T& obj)
{
if( Full() )
{
return 1;
}
m_arrBuf[m_uTail] = obj;
m_vecMark[m_uTail] = 1;
m_uTail += 1;
if( m_uTail >= m_uMaxBufLen )
{
m_uTail = 0;
}
return 0;
}
//从队列中取出一个元素
uint32_t Pop(T& obj)
{
if( Empty() )
{
return 1;
}
obj = m_arrBuf[m_uHead];
m_vecMark[m_uHead] = 0;
m_uHead += 1;
if( m_uHead >= m_uMaxBufLen )
{
m_uHead = 0;
}
return 0;
}
//获取队列元素个数
uint32_t ElemCount()
{
if( m_uTail >= m_uHead )
{
return (m_uTail - m_uHead);
}
if( m_uTail < m_uHead )
{
return (m_uMaxBufLen - ( m_uHead - m_uTail ) );
}
return 0;
}
void show()
{
for(uint32_t i=0; i<m_uMaxBufLen; i++)
{
if( m_vecMark[i] == 0 )
{
printf("pos %d have no element\n", i);
continue;
}
printf("pos %d element is: ", i);
m_arrBuf[i].show();
}
}
uint32_t Head()
{
return m_uHead;
}
uint32_t Tail()
{
return m_uTail;
}
private:
//貌似这里用vector是一个比较好的方法:可以比较一下两者的效率:即用数组和vector做一个对比
//std::vector<T> m_vecElem;
T* m_arrBuf;
std::vector<uint32_t> m_vecMark;
uint32_t m_uMaxBufLen;
uint32_t m_uHead;
uint32_t m_uTail;
};
#endif
//file: main.cpp
/*******************************************
* filename: main.cpp
* date: 2014-07-23 10:21
* author: jackie
* desc: function entrance
*******************************************/
#include "common_queue.h"
#include "common_struct.h"
int main()
{
CCommonQueue_T<STC_LOG, 10> logQueue;
uint32_t count = logQueue.ElemCount();
printf("common queue element count=%d\n", count);
for(uint32_t i=0; i<10; i++)
{
STC_LOG log;
std::string num;
char arr[10];
sprintf(arr, "%2d", i);
num = arr;
log.time = "2014-07-23 11:15:00";
log.content = "log index " + num;
log.level = 0;
uint32_t ret = 0;
ret = logQueue.Push(log);
if( ret > 0 )
{
printf("push element failed, errorcode=%d\n", ret);
}
}
for(uint32_t i=0; i<5; i++)
{
STC_LOG log;
uint32_t ret = 0;
ret = logQueue.Pop(log);
if( ret > 0 )
{
printf("pop element failed\n");
}
//log.show();
}
for(uint32_t i=0; i<10; i++)
{
STC_LOG log;
std::string num;
char arr[10];
sprintf(arr, "%2d", i);
num = arr;
log.time = "2014-07-23 11:15:00";
log.content = "log index " + num;
log.level = 0;
uint32_t ret = 0;
ret = logQueue.Push(log);
if( ret > 0 )
{
printf("push element failed, errorcode=%d\n", ret);
}
}
logQueue.show();
printf("head=%u, tail=%u\n", logQueue.Head(), logQueue.Tail());
printf("common queue test\n");
return 0;
}
//file: Makefile
TARGET:=common
INCDIR:=inc
##SRCDIR:=src
SRCDIR:=./
OBJDIR:=obj
$(shell if !([ -d $(OBJDIR) ]);then mkdir $(OBJDIR);fi)
LIBDIR:=lib
$(shell if !([ -d $(LIBDIR) ]);then mkdir $(LIBDIR);fi)
CC :=g++
FLAGS:=-Wall -W -I$(INCDIR) -D_DEBUG
LIBS :=-lpthread
##OPENCV=1 #switch of opencv
##ifdef OPENCV
##FLAGS+=`pkg-config --cflags opencv`
##LIBS +=`pkg-config --libs opencv`
##endif
#DBG=0
##ifdef DBG
FLAGS=-g -Wall
##else
##FLAGS+=-O2
##endif
## define lib
LIBS=-lpthread
##echo "include dir"
SRC:=$(wildcard $(SRCDIR)/*.cpp)
OBJ:=$(patsubst %.cpp,$(OBJDIR)/%.o,$(notdir $(SRC)))
#all:
# @echo $(OBJ)
#
$(TARGET):$(OBJ)
$(CC) -o $@ $^ $(FLAGS) $(LIBS)
$(OBJDIR)/%.o:$(SRCDIR)/%.cpp
$(CC) -c $< -o $@ $(FLAGS)
.PHONY: clean
clean:
rm -f $(OBJDIR)/*.o *~ core $(TARGET)
编译方法:
xiaoheqing@xiaoheqing-VirtualBox:~/mytest/muding$ make
执行程序:
xiaoheqing@xiaoheqing-VirtualBox:~/mytest/muding$ ./common
输出如下:
begin constructor
end constructor
common queue element count=0
push element failed, errorcode=1
push element failed, errorcode=1
push element failed, errorcode=1
push element failed, errorcode=1
push element failed, errorcode=1
push element failed, errorcode=1
push element failed, errorcode=1
pos 0 element is: loginfo time=2014-07-23 11:15:00, content=log index 2, level=0
pos 1 element is: loginfo time=2014-07-23 11:15:00, content=log index 3, level=0
pos 2 element is: loginfo time=2014-07-23 11:15:00, content=log index 4, level=0
pos 3 have no element
pos 4 have no element
pos 5 element is: loginfo time=2014-07-23 11:15:00, content=log index 5, level=0
pos 6 element is: loginfo time=2014-07-23 11:15:00, content=log index 6, level=0
pos 7 element is: loginfo time=2014-07-23 11:15:00, content=log index 7, level=0
pos 8 element is: loginfo time=2014-07-23 11:15:00, content=log index 0, level=0
pos 9 element is: loginfo time=2014-07-23 11:15:00, content=log index 1, level=0
head=5, tail=3
common queue test
begin deconstruct
end deconstruct
可以看到,程序实现了循环队列的效果,头和尾之间留两个单位的空闲,防止追尾【单位指的是模板中数据类型T】