作者:mobiledu2502940265 | 来源:互联网 | 2023-10-10 13:37
RingBuffer是什么? 正如名字所说的一样,它是一个环(首尾相接的环),你可以把它用做在不同上下文(线程)间传递数据的buffer。
基本来说,ringbuffer拥有一个序号,这个序号指向数组中下一个可用的元素。
随着你不停地填充这个buffer(可能也会有相应的读取),这个序号会一直增长,直到绕过这个环。
我们选择用环形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 itif (_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 0 0 1 0 2 0 … 0 20 0 0 1 1 2 2 3 … … n (<21) n&#43;1(<21)
第一圈写入的时候&#xff0c;尾不变&#xff0c;头增加&#xff0c;get_newest()
都是最新写入的数&#xff0c;在头部&#xff1b;get_oldest()
是第一个写入的数&#xff0c;在尾部。
写满一圈之后&#xff0c;get_newest()
的依然是最新写入的、头部的数&#xff1b;而get_oldest()
则是上一圈序号大于当前序号的一个数。因为环形缓冲区的大小是固定的&#xff0c;具有数组的性质&#xff0c;写入的数据不会丢弃&#xff0c;一直保存在缓冲区中。