一个有用的Queue程序

头文件

 

#ifndef QUEUE_H_H
#define QUEUE_H_H

#define UINT unsigned int
typedef void *HTWOBUFQUEUE;

//帧头结构
typedef struct QUEUENODE
{
 char* head;  //帧头本身数据
 char* data;
 UINT dataSize; //数据大小,不固定
}QUEUENODE_T, *PQUEUENODE_T;

/*-------------队列接口函数--------------*/

/*
 * 函  数:CreateQueue(),创建队列
 * 参  数:headNum,包数;headSize,帧头数据大小(可变部分大小),不是帧头大小;dataSize,数据平均大小
 * 返回值:成功返回所创建的队列句柄,失败返回NULL
 * 说  明:队列包含两个缓冲区,大小是分别:headNum * headSize,headNum * dataSize;
 */
HTWOBUFQUEUE CreateQueue(int headNum, int headSize, int dataSize);
int DestroyQueue(HTWOBUFQUEUE hq);

/*--------------------------------------*/

/*
 * 函  数:PushQueue()进队,使用时必须先创建队列
 * 参  数:hq,已创建的队列句柄;qHead,帧头指针
 * 返回值:成功返回0,失败返回-1
 */
int PushQueue(HTWOBUFQUEUE hq, PQUEUENODE_T qHead);

/*
 * 函  数:PushQueue()进队,使用时必须先创建队列
 * 参  数:hq,已创建的队列句柄;qHead,帧头指针;qHeadLen,qHead内存大小需大于队首元素大小
 * 返回值:失败返回-1,成功返回0,qHead中返回获取到的队首元素
 */
int PopQueue(HTWOBUFQUEUE hq, PQUEUENODE_T qHead, UINT qHeadLen);

/*
 * 函  数:ClearQueue(),清空队列,使用时必须先创建队列
 * 返回值:成功返回0,失败返回-1
 */
int ClearQueue(HTWOBUFQUEUE hq);

/*
 * 函  数:IfQueueEmpty()判断队列是否为空,为空返回1,否则返回0
 * 返回值:队列为空返回1,否则返回0
 */
int IfQueueEmpty(HTWOBUFQUEUE hq);

/*--------------------------------------*/

/*
 * 函  数:GetQueueMaxCount()获取队列可容纳的最大包数
 *     GetQueueCount()获取队列中的包数
 *     GetQueueFreeCount()获取队列当前还可以容纳的包数,可判断队列是否已满
 *     GetQueueMaxDataSize()获取队列可容纳数据的最大内存空间(以byte为单位)
 *      GetQueueFreeDataLen()获取队列当前剩余的内存空间
 */
UINT GetQueueMaxCount(HTWOBUFQUEUE hq);
UINT GetQueueCount(HTWOBUFQUEUE hq);
UINT GetQueueFreeCount(HTWOBUFQUEUE hq);

UINT GetQueueMaxDataSize(HTWOBUFQUEUE hq);
UINT GetQueueFreeDataSize(HTWOBUFQUEUE hq);

/*--------------------------------------*/

/*
 * 函  数:GetQueueHeadSize()获取队列帧头大小,因为队列结点中没有此数据结构
 *      GetQueueHeadDataLen()获取队列队首的数据大小
 * 说  明:这些函数不是必需的,可以废弃
 */
UINT GetQueueHeadSize(HTWOBUFQUEUE hq);
UINT GetQueueHeadDataLen(HTWOBUFQUEUE hq);

#endif

/*-------------------------------------------------------------------------------------*/

 

源文件

#include <tmStdLib.h>
#include <stdio.h>
#include "string.h"
#include <tmosal.h>

#include "Queue.h"

typedef struct PACKQUEUE
{
 //队列帧结构PQUEUENODE_T,由帧结点可得到帧头数据和可用数据位置
 PQUEUENODE_T fst;   //队列帧头
 PQUEUENODE_T lst;   //队列帧尾

 //队列帧buffer和数据buffer起始位置
 char* head;
 char* data;
 char* lstData;   //数据队尾指针,push使用

 //不变值
 UINT  headVarSize;  //单个桢头可变部分大小
 UINT headSize;   //帧头大小 = headVarSize + sizeof(QUEUENODE_T)
 UINT  headMaxNum;   //队列最大帧头数量
 UINT  averDataSize;  //队列平均数据大小
 UINT dataMaxSize;  //队列最大可容纳数据大小 = averDataSize * headMaxNum

 //変值
 UINT  curHeadCount;  //当前队列包数,即帧头数
 UINT freeHeadCount;
 //---
 UINT  curDataLen;   //当前队列数据大小,以byte为单位
 UINT freeDataSize;
 //---
 UINT fstHeadToEndCount; //fst->head距离队列缓冲区结束点距离(以帧数为单位)
 UINT fstDataToEndSize; //fst->data距离队列缓冲区结束点距离(以byte为单位)
 UINT lstHeadToEndCount; //lst->head距离队列缓冲区结束点距离(以帧数为单位)
 UINT lstDataToEndSize; //lst->data距离队列缓冲区结束点距离(以byte为单位)

 tmosalMutexHandle_t tmQueueLock; //queue lock
}PACKQUEUE_T, *PPACKQUEUE_T;

void InitQueue(PPACKQUEUE_T q, int headNum, int headSize, int dataSize);

//参数: dataSize---表示队列data的平均大小
HTWOBUFQUEUE CreateQueue(int headNum, int headSize, int dataSize)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 if(headSize < sizeof(QUEUENODE_T))
 {
  printf("CreateQueue() err: headSize is too small, headsize > %d", sizeof(QUEUENODE_T));
  return NULL;
 }
 
 q = (PPACKQUEUE_T)malloc(sizeof(PACKQUEUE_T));
 if(q == NULL)
 {
  printf("CreateQueue() err: malloc queue fail!/n");
  return NULL;
 }

 q->head = (char*)malloc(headNum * headSize);
 if(q->head == NULL)
 {
  printf("CreateQueue() err: malloc head fail!/n");
  free(q);
  return NULL;
 }
 
 q->data = (char*)malloc(headNum * dataSize);
 if(q->data == NULL)
 {
  printf("CreateQueue() err: malloc data fail!/n");
  free(q->head);
  free(q);
  return NULL;
 }

 //--------------------
 rval = tmosalMutexCreate(&q->tmQueueLock, tmosalMutexCreateFlagNone);
 if(TM_OK != rval)
 {
  free(q->head);
  free(q->data);
  free(q);
  printf("CreateQueue() err: Create Mutex fail!/n");
  return NULL;
 }
 //--------------------

 InitQueue(q, headNum, headSize, dataSize);

 return (HTWOBUFQUEUE)q;
}

void InitQueue(PPACKQUEUE_T q, int headNum, int headSize, int dataSize)
{
 q->headSize  = headSize;
 q->headVarSize = headSize - sizeof(QUEUENODE_T);
 q->headMaxNum = q->freeHeadCount = q->fstHeadToEndCount = q->lstHeadToEndCount = headNum;
 q->dataMaxSize  = q->freeDataSize = q->fstDataToEndSize = q->lstDataToEndSize = dataSize * headNum;
 q->averDataSize = dataSize;
 q->curHeadCount = 0;
 q->curDataLen = 0;

 q->fst = q->lst = (PQUEUENODE_T)q->head;

 q->fst->head = q->lst->head = q->head + sizeof(QUEUENODE_T);
 q->fst->data = q->lst->data = q->lstData = q->data;
}

//-------------------
int DestroyQueue(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = (PPACKQUEUE_T)hq;

 if(q == NULL)
 {
  return 0;
 }

 if(q->head != NULL)
 {
  free(q->head);
  q->head = NULL;
 }

 if(q->data != NULL)
 {
  free(q->data);
  q->data = NULL;
 }

 //------------------
 rval = tmosalMutexDestroy(q->tmQueueLock);
 if(TM_OK != rval)
 {
  printf("DestroyQueue() err: destroy Mutex fail!/n");
  return -1;
 }
 //------------------

 free(q);
 q = NULL;

 return 0;
}

//----------------------
int PushQueue(HTWOBUFQUEUE hq, PQUEUENODE_T qHead)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 int ret = 0;

 //error check
 if(hq == NULL || qHead == NULL)
 {
  printf("PushQueue() err: HTWOBUFQUEUE is NULL, queue is NULL!/n");
  return -1;
 }

 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);               //ENTER MUTEX
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return -1;
 }

 //check queue free space
 if(q->freeHeadCount <= 0 || q->freeDataSize < qHead->dataSize)
 {
  printf("PushQueue() err: queue is full or dataSize is too large! freeHeadCount = %d, freeData = %d(b)/n", q->freeHeadCount, q->freeDataSize);
  ret = -1;
 }
 else
 {
  //qHead进队
  memcpy(q->lst->head, qHead->head, q->headVarSize);  //帧头可变数据部分

  q->lst->data = q->lstData;
  if(qHead->dataSize > q->lstDataToEndSize)    //the end of q->data
  {
   UINT dataOverLen = qHead->dataSize - q->lstDataToEndSize;
   //printf("****************push to end!...dataOverLen = %d, freeHeadCount = %d, freeDataLen = %d/n", dataOverLen, q->freeHeadCount, q->freeDataSize);
   memcpy(q->lst->data, qHead->data, q->lstDataToEndSize);
   memcpy(q->data, qHead->data + q->lstDataToEndSize, dataOverLen);
   q->lstDataToEndSize = q->dataMaxSize - dataOverLen;
  }
  else
  {
   memcpy(q->lst->data, qHead->data, qHead->dataSize);
   if((q->lstDataToEndSize -= qHead->dataSize) == 0)      //the end of q->data
   {
    q->lstDataToEndSize = q->dataMaxSize;
   }
  }
  
  q->lst->dataSize = qHead->dataSize;

  q->curHeadCount++;
  q->freeHeadCount--;
  q->curDataLen += q->lst->dataSize;
  q->freeDataSize -= q->lst->dataSize;
  
  //lst后移
  if(--(q->lstHeadToEndCount) == 0)      //the end of head
  {
   q->lst = (PQUEUENODE_T)q->head;  
   q->lstHeadToEndCount = q->headMaxNum;
  }
  else
  {
   q->lst = (PQUEUENODE_T)((char*)q->lst + q->headSize);
  }

  q->lst->head = (char*)q->lst + sizeof(QUEUENODE_T);
  q->lstData = q->data + (q->dataMaxSize - q->lstDataToEndSize);
    }

 rval = tmosalMutexExit(q->tmQueueLock);      //EXIT MUTEX
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return -1;
 }

 return ret;
}

//-------------------
//出队,qHeadLen是qHead指针所的缓冲区大小
int PopQueue(HTWOBUFQUEUE hq, PQUEUENODE_T qHead, UINT qHeadLen)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 int ret = 0;

 if(hq == NULL || qHead == NULL)
 {
  printf("PopQueue() err: HTWOBUFQUEUE is NULL, queue is NULL!/n");
  return -1;
 }

 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);               //ENTER MUTEX
 if(TM_OK != rval)
 {
  printf("PopQueue() err: enter Mutex fail/n");
  return -1;
 }

 //--------
 if(q->curHeadCount == 0)
 {
  printf("PopQueue() err: queue is empty!/n");
  ret = -1;
 }
 else if(qHeadLen < (q->fst->dataSize + q->headSize))
 {
  printf("PopQueue() err: qHeadLen is too small, minSize = %d(b)/n", q->fst->dataSize + q->headSize);
  ret = -1;
 }
 else
 {
  memset(qHead, 0, qHeadLen);
  qHead->head = (char*)qHead + sizeof(QUEUENODE_T);
  qHead->data = (char*)qHead + q->headSize;
  qHead->dataSize = q->fst->dataSize;

  //拷贝数据
  memcpy(qHead->head, q->fst->head, q->headVarSize);
  if(qHead->dataSize <= q->fstDataToEndSize)    //data是否跨尾
  {
   //no
   memcpy(qHead->data, q->fst->data, qHead->dataSize);
   if((q->fstDataToEndSize -= qHead->dataSize) == 0) //进队后data到达队列边界
   {
    q->fstDataToEndSize = q->dataMaxSize;
   }
  }
  else
  {
   //yes
   UINT dataOverLen = qHead->dataSize - q->fstDataToEndSize;
   memcpy(qHead->data, q->fst->data, q->fstDataToEndSize);
   memcpy(qHead->data + q->fstDataToEndSize, q->data, dataOverLen);
   q->fstDataToEndSize = q->dataMaxSize - dataOverLen;
   //printf("******************pop end!/n");
  }

  q->curHeadCount--;
  q->freeHeadCount++;
  q->curDataLen -= q->fst->dataSize;
  q->freeDataSize += q->fst->dataSize;
  
  //fst后移
  if(--(q->fstHeadToEndCount) == 0)      //if the end of head
  {
   q->fst = (PQUEUENODE_T)q->head;
   q->fstHeadToEndCount = q->headMaxNum;
  }
  else
  {
   q->fst = (PQUEUENODE_T)((char*)q->fst + q->headSize);
  }
  q->fst->head = (char*)q->fst + sizeof(QUEUENODE_T);
  q->fst->data = q->data + (q->dataMaxSize - q->fstDataToEndSize);
 }

 rval = tmosalMutexExit(q->tmQueueLock);      //EXIT MUTEX
 if(TM_OK != rval)
 {
  printf("PopQueue() err: exit Mutex fail/n");
  return -1;
 }

 return 0;
}

int ClearQueue(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = Null;
 if(hq == NULL)
 {
  return -1;
 }
 
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);    /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("ClearQueue() err: enter Mutex fail/n");
  return -1;
 }

 if(q->curHeadCount != 0)
 {
  q->curHeadCount = 0;
  q->freeHeadCount = q->fstHeadToEndCount = q->lstHeadToEndCount = q->headMaxNum;
  q->curDataLen = 0;
  q->freeDataSize = q->fstDataToEndSize = q->lstDataToEndSize = q->dataMaxSize;

  q->fst = q->lst = (PQUEUENODE_T)q->head;
  q->fst->head = q->lst->head = q->head + sizeof(QUEUENODE_T);
  q->fst->data = q->lst->data = q->lstData = q->data;
 }
 
 rval = tmosalMutexExit(q->tmQueueLock);      /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("ClearQueue() err: exit Mutex fail/n");
  return -1;
 }
 
 return 0;
}

int IfQueueEmpty(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 int ret = -1;

 if(q == NULL)
 {
  return -1;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return -1;
 }

 ret = (q->curDataLen == 0);
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return -1;
 }
 
 return ret;
}

UINT GetQueueMaxCount(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->headMaxNum;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

UINT GetQueueCount(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;
 
 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->curHeadCount;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

//可以用来判断队列是否已满,有可能队列未满,但是放不下较大的数据,可以用GetQueueFreeDataLen()查看
UINT GetQueueFreeCount(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->freeHeadCount;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

UINT GetQueueMaxDataSize(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->dataMaxSize;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

UINT GetQueueFreeDataSize(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->freeDataSize;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

//获取队列帧头大小,因为队列结点中没有此数据结构
UINT GetQueueHeadSize(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->headSize;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

//获取队列队首的数据大小
UINT GetQueueHeadDataLen(HTWOBUFQUEUE hq)
{
 tmErrorCode_t rval = TM_OK;
 PPACKQUEUE_T q = NULL;
 UINT ret = 0;

 if(q == NULL)
 {
  return 0;
 }
 q = (PPACKQUEUE_T)hq;

 rval = tmosalMutexEnter(q->tmQueueLock, Null);     /* ENTER MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: enter Mutex fail/n");
  return 0;
 }

 ret = q->fst->dataSize;
 
 rval = tmosalMutexExit(q->tmQueueLock);       /* EXIT MUTEX */
 if(TM_OK != rval)
 {
  printf("PushQueue() err: exit Mutex fail/n");
  return 0;
 }
 
 return ret;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值