RingBuffer环形缓冲区的数值操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oqqENvY12/article/details/79898744

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
0 0
1 0
2 0
0
20 0
0 1
1 2
2 3
n (<21) n+1(<21)
  • 第一圈写入的时候,尾不变,头增加,get_newest()都是最新写入的数,在头部;get_oldest()是第一个写入的数,在尾部。

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

猜你喜欢

转载自blog.csdn.net/oqqENvY12/article/details/79898744
今日推荐