【C语言循环队列实现】

/*
* 循环队列,单位为字节
* out == in的时候ring buf为空
* 往cache里面写数据时,直接往in处写数据,写完后in++
* 从cache里面读数据时,直接读out处的数据,读完后out++
*/
typedef struct k_cache_struct
{
	uint8_t *buf;
	int32_t vol;
	int32_t in;
	int32_t out;
	int32_t flag;
}k_cache_t;

/*
* 循环队列状态
*/
enum k_cache_flag
{
	CACHE_INIT	= 0,
	CACHE_END,
	CACHE_ERR,
};
//返回当前cache的剩余数据量大小
static int32_t k_cache_size_data(k_cache_t *cache)
{
	int32_t tmp = cache->in - cache->out;
	if(tmp < 0)
	{
		return tmp + cache->vol;
	}
	return tmp;
}

//返回当前cache剩余空间大小。为了防止buf被写满,返回的empty大小比真实的empty少4字节
static int32_t k_cache_size_empty(k_cache_t *cache)
{
	int32_t tmp = cache->out - cache->in;
	if(tmp <= 0)
	{
		tmp += cache->vol;
	}
	
	tmp = tmp > 4 ? tmp - 4 : 0;
	return tmp;
}
int32_t k_cache_init(k_cache_t *cache, void *buf, int32_t size)
{
	cache->buf 	= buf;
	cache->vol 	= size;
	cache->in  	= 0;
	cache->out  = 0;
	cache->flag = CACHE_INIT;
	
	return 0;
}
/*
* 读取cache里面size字节大小的数据到buf中,如果数据不够的话会一直阻塞在这里
*/
int32_t k_cache_read(k_cache_t *cache, void *buf, int32_t size)
{
    int32_t i, rev;
	uint8_t *dst;
	while(1)
	{
		rev = k_cache_size_data(cache);
		if(rev >= size)
		{
			rev = size; //数据量够,直接返回所需的size字节
			break;
		}
		else if(cache->flag == CACHE_END)
		{
			size = rev; //数据量不够且cache end,返回cache中剩余的数据
			break;
		}
		else if(cache->flag == CACHE_ERR)
		{
			printf("[cache]cache read err\n");
			return -1; //数据量不够且cache error,直接返回错误
		}
		os_thread_sleep(10);
	}
	
	i = cache->out;
	dst = (uint8_t *)buf;
	while(rev > 0)
	{
		*dst++ = cache->buf[i++]; //读取cache里面的数据到dst中
		if(i >= cache->vol){
			i = 0;
		}
		rev--;
	}
	
	cache->out = i;
	return size;
}
/*
* 将buf中的size字节大小数据写入到cache当中
*/
int32_t k_cache_write(k_cache_t *cache, void *buf, int32_t size)
{
	int32_t i, rev;
	uint8_t *src;
	
#if 0 //如果空间不够的话会一直阻塞在这里
	while(1)
	{
		rev = k_cache_size_empty(cache);
		if(rev >= size)
		{
			rev = size; //剩余的空间够,直接返回所需的size字节
			break;
		}
		else if(cache->flag == CACHE_END)
		{
			size = rev; //剩余的空间不够且cache end,返回cache中剩余的空间
			break;
		}
		else if(cache->flag == CACHE_ERR)
		{
			printf("[cache]cache write err\n");
			return -1; //剩余的空间不够且cache error,直接返回错误
		}
		os_thread_sleep(10);
	}
#else //如果空间不够的话直接返回0
	rev = k_cache_size_empty(cache);
	if(rev >= size)
	{
		rev = size; 
	}
	else if(cache->flag == CACHE_END)
	{
		return 0;
	}
	else if(cache->flag == CACHE_ERR)
	{
		printf("[cache]cache write err\n");
		return -1;
	}
	else
	{
		return 0;
	}
#endif
	
	i = cache->in;
	src = (uint8_t *)buf;
	while(rev > 0)
	{
		cache->buf[i++] = *src++; //将src数据写入到cache当中
		if(i >= cache->vol){
			i = 0;
		}
		rev--;
	}
	
	cache->in = i;
	return size;
}
void k_cache_set_end(k_cache_t *cache)
{
	cache->flag = CACHE_END;
}

void k_cache_set_err(k_cache_t *cache)
{
	cache->flag = CACHE_ERR;
}

int32_t k_cache_flag_get(k_cache_t *cache)
{
    return cache->flag;
}
//示例代码
k_cache_t cache = {0};
void main(void)
{
	uint8_t *buf = (uint8_t *)malloc(1024);
	if(buf == NULL)
		return;
	k_cache_init(&cache, buf, 1024); //开辟一个大小为1k的ring buffer
	
	uint8_t *write_buf = (uint8_t *)malloc(64); //每次往cache里面写64字节数据
	if(write_buf == NULL)
		return;
	memset(write_buf, 0x55, 64);
	
	uint8_t *read_buf = (uint8_t *)malloc(64); //每次从cache里面读64字节数据
	if(read_buf == NULL)
		return;
	
	while(1)
	{
		k_cache_write(&cache, write_buf ,64);
		k_cache_read(&cache, read_buf ,64);
		os_thread_sleep(10);
	}
	
	return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴子坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值