循环队列及C语言实现<三>
来源:互联网 发布:企业融资方式 知乎 编辑:程序博客网 时间:2024/05/16 04:19
在之前的博客中给出了设计循环队列的思路以及源码,这些可都是经过我长期大数据测试的验证哦。当然,现在的很多开源项目和一些封装好的类或接口也都有类似的队列实现方法,之所以我还在使用自己写的这一套方法,主要是因为灵活性较大,我可以定制出适合自己的接口。而且在其上的操作逻辑和结果我也心知肚明。
好了,之所以隔了这么久写这个第三篇文章,主要是考虑到以下因素:
<1> 队列并发操作的同步问题;(安全性)
<2> 部分情况下,希望在读取队列后进行队列回写操作。(比如进行数据分析按一帧一帧进行解析的时候,发现队列里缓存数据不足一帧,此时就需要回写,等再有数据保存到队列)
下面先提出 <1> 的解决方法,使用互斥锁和信号量,给出简单例子:
Exp1:
pthread_mutex_init(&mutex);thread1: ... pthread_mutex_lock(&mutex); WriteQueue(q, wbuf, writelen); pthread_mutex_unlock(&mutex); ...thread2: ... pthread_mutex_lock(&mutex); ReadQueue(q, rbuf, &readlen); pthread_mutex_unlock(&mutex); ...
Exp2:
sem_init(&sem);thread1: ... sem_wait(&sem); WriteQueue(q, wbuf, writelen); sem_post(&sem); ...thread2: ... sem_wait(&sem); ReadQueue(q, rbuf, &readlen); sem_post(&sem); ...
其他的方式还有很多啦,就不一一列举了,小型项目开发应该是足够了。
至于方案 <2> 的解决方法,在 queue.c 中添加一个回写函数就好啦,原理也很简单,把读指针移动到之前的位置就可以啦。需要考虑的就是回写的长度大于队列当前读指针距离队列头的位置时的处理,详细可以参见我下面的代码:
unsigned int RecoverReadQueue(Queue *q, unsigned int len){ unsigned int ret = 0; unsigned int rest = q->read; if (rest >= len) { q->read -= len; } else { q->read = q->size - (len - rest); } q->space -= len; return ret;}
为了防止部分读者忽略了之前文章,我还是把最新的源码贴出来以供参考:
queue.h
#ifndef _QUEUE_H#define _QUEUE_H#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>/** * Queue - queue structure * @buf: queue buffer * @read: position of read * @write: position of write * @size: buffer size * @space: writable buffer size */typedef struct { unsigned char *buf; unsigned int read; unsigned int write; unsigned int size; unsigned int space; bool OverFlow;} Queue;#define Avail(q) (q->size - q->space)extern bool Queue_Empty(Queue *q);extern bool Queue_Full(Queue *q);extern unsigned int RecoverReadQueue(Queue *q, unsigned int len);extern void Queue_Init(Queue *q, int size);extern void Queue_Destroy(Queue *q);extern bool AddQueue(Queue *q, unsigned char val);extern bool DelQueue(Queue *q, unsigned char *val);extern unsigned int WriteQueue(Queue *q, unsigned char *buf, unsigned int len);extern unsigned int ReadQueue(Queue *q, unsigned char *buf, unsigned int len);#endif
queue.c
/* * Queue operation API - 1.1 * * Copyright (C) 2016 SoldierJazz (SoldierJazz@163.com) * * This program is free software; you can redistribute it and/or * modify it. * */#include "queue.h"/** * Queue_Init - init a queue * @q: pointer of queue * @size: size of buffer in queue * * Must be called when started. */void Queue_Init(Queue *q, int size){ q->buf = (unsigned char *)malloc(sizeof(unsigned char) * size); memset(q->buf, 0x00, size); q->read = 0; q->write = 0; q->size = size; q->space = size; q->OverFlow = false;}/** * Queue_Destroy - destroy a queue * @q: pointer of queue */void Queue_Destroy(Queue *q){ free(q->buf);}/** * Queue_Empty - tests whether a queue is empty * @q: the queue to test */bool Queue_Empty(Queue *q) { return (q->space == q->size);}/** * Queue_Full - tests whether a queue is full * @q: the queue to test */bool Queue_Full(Queue *q){ return (q->space == 0);}/** * AddQueue - add a byte to queue * @q: the queue to add to * @val: the char to add */boolbool AddQueue(Queue *q, unsigned char val){ if (!Queue_Full(q)) { q->buf[q->write] = val; q->write = (q->write + 1) % q->size; q->space--; return true; } return false;}/** * DelQueue - delete a byte from queue * @q: the queue to delete from * @val: the char deleted */bool DelQueue(Queue *q, unsigned char *val){ if (!Queue_Empty(q)) { *val = q->buf[q->read]; q->read = (q->read + 1) % q->size; q->space++; return true; } return false;}/** * WriteQueue - write buffers to queue * @q: the queue to write in * @buf: pointer of write buffer * @len: length of write buffer */unsigned int WriteQueue(Queue *q, unsigned char *buf, unsigned int len){ unsigned int ret = 0; unsigned int rest = q->size - q->write; if (!Queue_Full(q)) { if (q->space >= len) { ret = len; if (rest >= len) { memcpy(q->buf + q->write, buf, len); q->write = (q->write + len) % q->size; q->space -= len; } else { memcpy(q->buf + q->write, buf, rest); q->write = 0; memcpy(q->buf, buf + rest, len - rest); q->write = len -rest; q->space -= len; } } else { ret = q->space; if (rest >= q->space) { memcpy(q->buf + q->write, buf, q->space); q->write = (q->write + q->space) % q->size; q->space = 0; } else { memcpy(q->buf + q->write, buf, rest); q->write = 0; memcpy(q->buf, buf + rest, q->space - rest); q->write = q->space -rest; q->space = 0; } } } return ret;}/** * RecoverReadQueue - recover len of buffer from queue * @q: the queue to recover from * @len: recover length */unsigned int RecoverReadQueue(Queue *q, unsigned int len){ unsigned int ret = 0; unsigned int rest = q->read; if (rest >= len) { q->read -= len; } else { q->read = q->size - (len - rest); } q->space -= len; return ret;}/** * ReadQueue - read buffers from queue * @q: the queue to read from * @buf: pointer of read buffer * @len: read length */unsigned int ReadQueue(Queue *q, unsigned char *buf, unsigned int len){ unsigned int rest = q->size - q->read; unsigned int ret = 0; if (!Queue_Empty(q)) { if (Avail(q) >= len) { ret = len; if (rest >= len) { memcpy(buf, q->buf + q->read, len); q->read = (q->read + len) % q->size; q->space += len; } else { memcpy(buf, q->buf + q->read, rest); q->read = 0; memcpy(buf + rest, q->buf, len - rest); q->read = len -rest; q->space += len; } return len; } else { ret = Avail(q); if (rest >= Avail(q)) { memcpy(buf, q->buf + q->read, Avail(q)); q->read = (q->read + Avail(q)) % q->size; q->space = q->size; } else { memcpy(buf, q->buf + q->read, rest); q->read = 0; memcpy(buf + rest, q->buf, Avail(q) - rest); q->read = Avail(q) -rest; q->space = q->size; } } } return ret;}
2 0
- 循环队列及C语言实现<三>
- 循环队列及C语言实现<一>
- 循环队列及C语言实现<二>
- 循环队列C语言实现
- c语言实现循环队列
- C语言实现循环队列
- C语言实现循环队列
- C语言实现循环队列
- 数据结构(C语言)实现循环队列
- 循环队列的实现(C语言)
- 数据结构C语言实现之循环队列
- 数据结构.循环队列(C语言实现)
- c语言循环线性队列的实现
- 数据结构:循环队列(C语言实现)
- 循环队列的实现(C语言)
- 顺序循环队列的c语言实现
- 数据结构:循环队列(C语言实现)
- 数据结构C语言实现之循环队列
- 安卓插件化几个模块学习
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
- Python第三天
- 《C++ Primer Plus(第六版)》(29)(第十四章 C++中的代码重用 复习题答案)
- 博为峰Java技术文章 ——JavaEE Hibernate初始化类
- 循环队列及C语言实现<三>
- 数组去重
- 单字符I/O:getchar()和putchar()
- NYOJ27水池数目(dfs)
- chmod权限
- git备忘录
- JavaWeb日记——Springboot 热部署的两种方式
- 计算字符串t在字符串s中出现的次数(KMP)
- MySQL查询语句大全