当前位置: 首页 > 科技观察

软件开发实践中enqueue和dequeue操作的C代码示例

时间:2023-03-19 09:57:55 科技观察

概述最近有在校的同学朋友问我数据结构中的queue在实际的软件开发项目中有什么样的用处。大家都知道队列的特点是先进先出,即数据按照进入队列的先后顺序出队。在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列可以发挥很大的作用。我们可以将接收到的数据存储在一个全局队列中,然后在另一个程序流中从同一个全局队列中取出数据,经过一定处理后将消息发送给另一个模块。这样做可以减少程序的性能瓶颈。本文使用实际的C代码来说明数据入队和出队的简单方法。可以据此了解队列的实际使用情况,也可以参考实现更复杂的队列操作。C代码/**************************************************************************Copyright(C)2016,ZhouZhaoxiong**文件名:QueueUse.c*文件标识:无*内容摘要:示例使用ofqueues(enqueueandexit)*其他说明:无*当前版本:V1.0*作者:ZhouZhaoxiong*完成日期:20160811****************************************************************************/#include#include#include#include#include//重新定义数据类型typedefsignedintINT32;typedefunsignedintUINT32;typedefunsignedcharUINT8;//宏定义#defineMAX_QUEUE10000//***队列元素个数//结构变量typedefstruct{UINT32iID;//个数UINT8szInfo[100];//说明}T_StructInfo;//全局变量定义T_StructInfog_tQueue[MAX_QUEUE]={0};//queuestructureUINT32g_iQueueHead=0;//queueheadindexUINT32g_iQueueTail=0;//queuetailindexpthread_mutex_tg_mutex_queue_cs;//mutexsemaphorepthread_cond_tqueue_cv;pthread_mutexattr_tg_MutexAttr;//functiondeclarationvoidQueidDataIntoQueue(Getvoid));INT32EnQueue(T_StructInfotQueueData);INT32DeQueue(T_StructInfo*ptStructData);voidSleep(UINT32iCountMs);/****************************************************************************函数说明:主要函数*输入参数:无*输出参数:无*返回值:0-执行完成*其他说明:无*修改日期版本号修改内容修改*------------------------------------------------------------*20160811V1.0ZhouZhaoxiong创建*********************************************************************/INT32main(void){pthread_mutex_init(&g_mutex_queue_cs,&g_MutexAttr);pthread_cond_init(&queue_cv,NULL);//在循环中执行入队和出队操作while(1){PutDataIntoQueue();//DataEnqueueSleep(5*1000);//间隔5秒GetDataFromQueue();//DataoutQueueSleep(60*1000);//每分钟执行一次dequeue和enqueue}return0;}/*************************************************************************函数说明:向队列中添加数据*输入参数:无*输出参数:无*返回值:0-成功-1-失败*其他说明:无*修改日期版本sionNo.Modifier修饰内容*---------------------------------------------------------*20160811V1.0周兆雄创建********************************************************************/voidPutDataIntoQueue(void){T_StructInfoQueueData={0};staticUINT32iCountNum=0;//给结构体的变量赋值tQueueData.iID=iCountNum;snprintf(tQueueData.szInfo,sizeof(tQueueData.szInfo)-1,"周%d",iCountNum);//计数值累加iCountNum++;if(iCountNum>=MAX_QUEUE-1){iCountNum=0;}//向队列添加数据(等添加成功后退出)while(EnQueue(tQueueData)==-1){Sleep(1000);//加入失败,1秒后重试}//打印加入的数据printf("PutDataIntoQueue:ID=%d,Info=%s\n",tQueueData.iID,tQueueData.szInfo);}/********************************************************************函数说明:从队列中取出数据*输入参数:无*输出参数:无*返回值:0-success-1-Failed*其他说明:None*ModifiedDateVersionNumberModifiedByModifiedContent*-------------------------------------------------------------*20160811V1.0ZhouZhaoxiong创建**********************************************************************/voidGetDataFromQueue(void){T_StructInfoQueueData={0};if(DeQueue(&tQueueData)==-1){return;}//打印获取到的数据printf("GetDataFromQueue:ID=%d,Info=%s\n",tQueueData.iID,tQueueData.szInfo);}/********************************************************************函数说明:数据入队列*输入参数:tQueueData-队列数据*输出参数:无*返回值:0-成功-1-失败*其他说明:无*修改日期版本号修改人修改内容*--------------------------------------------------------------*20160811V1.0周兆雄g创建*******************************************************************/INT32EnQueue(T_StructInfoQueueData){INT32iRetVal=0;UINT32iNextPos=0;pthread_mutex_lock(&g_mutex_queue_cs);iNextPos=g_iQueueTail+1;if(iNextPos>=MAX_QUEUE){iNextPos=0;}if(iNextPos==g_iQueueHead){iRetVal=-1;//已经达到队列的最大长度}else{//进入队列memset(&g_tQueue[g_iQueueTail],0x00,sizeof(T_StructInfo));memcpy(&g_tQueue[g_iQueueTail],&tQueueData,sizeof(T_StructInfo));g_iQueueTail=iNextPos;}pthread_cond_signal(&queue_cv);pthread_mutex_unlock(&g_mutex_queue_cs);returniRetVal;}/***********************************************************************函数说明:数据出队列*输入参数:ptStructData-队列数据*输出参数:无*返回值:0-成功-1-失败*其他说明:无*修改日期版本号修改内容修改*-----------------------------------------------------------*20160811V1.0周兆雄创建******************************************************************/INT32DeQueue(T_StructInfo*ptStructData){T_StructInfoQueueData={0};if(ptStructData==NULL){return-1;}pthread_mutex_lock(&g_mutex_queue_cs);while(g_iQueueHead==g_iQueueTail){pthread_cond_wait(&queue_cv,&g_mutex_queue_cs);}memset(&tQueueData,0x00,sizeof(T_StructInfo));memcpy(&tQueueData,&g_tQueue[g_iQueue_Head],++HegucizetOf_Head);如果(g_iQueueHead>=MAX_QUEUE){g_iQueueHead=0;}pthread_mutex_unlock(&g_mutex_queue_cs);memcpy(ptStructData,&tQueueData,sizeof(T_StructInfo));return0;}/******************************************************************************函数说明:程序睡眠*输入参数:iCountMs-睡眠时间(单位:ms)*输出参数:无*返回值:无*其他说明:无*修改日期,版本号,修改者修改内容*-------------------------------------------------------------*20160811V1.0ZhouZhaoxiong创建**************************************************************************/voidSleep(UINT32iCountMs){structtimevalt_timeout={0};if(iCountMs<1000){t_timeout.tv_sec=0;t_timeout.tv_usec=iCountMs*1000;}else{t_timeout.tv_sec=iCountMs/1000;t_timeout.tv_usec=(iCountMs%1000)*1000;}select(0,NULL,NULL,NULL,&t_timeout);//调用select函数阻塞程序文件,执行“QueueUse”命令,可以看到程序的运行结果(结果会不断更新)如下:~/zhouzx/Test/QueueUse>QueueUsePutDataIntoQueue:ID=0,Info=zhou0GetDataFromQueue:ID=0,Info=zhou0PutDataIntoQueue:ID=1,Info=zhou1GetDataFromQueue:ID=1,Info=zhou1PutDataIntoQueue:ID=2,Info=zhou2GetDataFromQueue:ID=2,Info=zhou2PutDataIntoQueue:ID=3,Info=zhou3GetDataFromQueue:ID=3,info=zhou3我们看到,数据先加入队列,再从队列中取出。程序说明***,在本程序中,enqueue和dequeue是在同一个函数中完成的,但是在实际开发项目的程序中,enqueue和dequeue一般是在不同的程序流程中(两者在不同的线程中完成)。二、本程序的数据入队操作在EnQueue函数中完成,数据出队操作在DeQueue函数中完成。全局变量g_tQueue用于存放需要处理的数据。第三,在实际开发项目的程序中,可能会有很多进程调用入队和出队函数。为了防止多个进程同时向队列中添加数据或从队列中取数据,使用了EnQueue和DeQueue函数。锁定操作。也就是说,在对数据进行操作之前,通过pthread_mutex_lock函数进行加锁操作,在数据处理完毕之后,通过pthread_mutex_unlock函数进行解锁操作。第四,在实际开发项目中,为了防止程序从队列中取数据过快导致下游模块无法处理,我们往往会在从队列中取出数据后发送消息的过程中控制数据发送速率队列。每秒发送的消息数可以在配置文件中设置。【本文为专栏作家周兆雄原创,转载请征得作者授权】