RingBuffer环形缓冲区的数值操作

RingBuffer是什么?

正如名字所说的一样,它是一个环(首尾相接的环),你可以把它用做在不同上下文(线程)间传递数据的buffer。

ring1

基本来说,ringbuffer拥有一个序号,这个序号指向数组中下一个可用的元素。

ring2

随着你不停地填充这个buffer(可能也会有相应的读取),这个序号会一直增长,直到绕过这个环。

ring3

我们选择用环形buffer的最初原因就是想要提供可靠的消息传递。我们需要将已经被服务发送过的消息保存起来,这样当另外一个服务通过nak (拒绝应答信号)告诉我们没有成功收到消息时,我们能够重新发送给他们。


下面介绍一下PX4源码中关于RingBuffer的数据写入与取值过程,代码如下

/**
 * Ringbuffer.h
 *  
 * int _head = _tail = 0;
 * size = 21
 */
inline void push(data_type sample)
{
	int head_new = _head;

	if (_first_write) {
		head_new = _head;

	} else {
		head_new = (_head + 1) % _size;
	}

	_buffer[head_new] = sample;
	_head = head_new;

	// move tail if we overwrite it
	if (_head == _tail && !_first_write) {
		_tail = (_tail + 1) % _size;

	} else {
		_first_write = false;
	}
}

inline data_type get_oldest()
{
	return _buffer[_tail];
}

unsigned get_oldest_index()
{
	return _tail;
}

inline data_type get_newest()
{
	return _buffer[_head];
}

整个写入过程中_head_tail的变化过程如下表所示:

_head_tail
00
10
20
0
200
01
12
23
n (<21)n+1(<21)
  • 第一圈写入的时候,尾不变,头增加,get_newest()都是最新写入的数,在头部;get_oldest()是第一个写入的数,在尾部。

  • 写满一圈之后,get_newest()的依然是最新写入的、头部的数;而get_oldest()则是上一圈序号大于当前序号的一个数。因为环形缓冲区的大小是固定的,具有数组的性质,写入的数据不会丢弃,一直保存在缓冲区中。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值