HackRF 频谱仪之 RingBuffer(二)
在上一个 RingBuffer 介绍中,我们最后提到在使用 ringbuffer 的 push 和 pop 函数时,都是需要传入 ringbuffer 的地址,而并非变量。其原因是在 C 语言中传入结构体 变量时,实际上都是传入的这个变量的副本,因此我们修改的是这个副本,而非变量本身。所以这样就会遇到一个问题,当多次调用这个 ringbuffer 函数时,结构体都被重新 copy 了一份,也就是说这个 ringbuffer 都是全新的,也就失去了 ringbuffer 的作用了。
下面我们以两个例子进行说明,首先我们重新写一个 ringbuffer 的 push 功能,与上一篇 blog 中的区别在于将传递的参数 ringbuffer 的地址改为 ringbuffer 变量,如下所示:
```C
void ring_buffer_push_test(RING_BUFFER ringBuffer, int data_num, int *data){
pthread_mutex_lock(&ringBuffer.ring_mutex);
// Process the data in buffer one by one
for (int i=0;i<data_num;i++){
int previous_head = ringBuffer.head;
// Add data
ringBuffer.data[ringBuffer.head] = data[i];
// Add Header
ringBuffer.head = ((ringBuffer.head) + 1) % BUFFER_SIZE;
// Count ++, if not full
if(ringBuffer.count < BUFFER_SIZE){
ringBuffer.count = ringBuffer.count+1;
}
// Deal with Tail when BUFFER is FULL. Keep counts the same
else{
ringBuffer.tail = (ringBuffer.tail+1)%BUFFER_SIZE;
}
printf("Ring Buffer No. %i Push-In, head = %i, tail = %i, inputData = %i, DataToRead = %i \n",ringBuffer.buffer_No,ringBuffer.head,ringBuffer.tail, ringBuffer.data[previous_head],ringBuffer.count);
}
pthread_cond_signal(&ringBuffer.ring_cond);
pthread_mutex_unlock(&ringBuffer.ring_mutex);
}
```
接下来,我们分别创建两个 ringbuffer 的实例,一个的 bufferNo.= 1, 另一个的 = 2.
```C
static RING_BUFFER ringbuffer = {
.buffer_No = 1,
.head = 0,
.tail = 0,
.count = 0,
.ring_mutex = PTHREAD_MUTEX_INITIALIZER,
.ring_cond = PTHREAD_COND_INITIALIZER
};
static RING_BUFFER ringbuffer1 = {
.buffer_No = 2,
.head = 0,
.tail = 0,
.count = 0,
.ring_mutex = PTHREAD_MUTEX_INITIALIZER,
.ring_cond = PTHREAD_COND_INITIALIZER
};
```
然后我们在 Producer 线程中对两个 ringbuffer 分别写入数据,我们先用上一篇 blog 中的方法,也就是传入 ringbuffer 地址的方式进行写入:
```C
void* Producer_Pthread() {
while (keep_running) {
for (int i = 0; i < WRITE_NUM; i++) {
a[i] = a[i] + i;
}
// VERY IMPORTANT HERE TO USE THE ADDRESS OF RINGBUFFER !!!
ring_buffer_push(&ringbuffer, WRITE_NUM, a);
sleep(1);
for (int i=0; i< WRITE_NUM1;i++){
b[i] = b[i]+i;
}
ring_buffer_push(&ringbuffer1,WRITE_NUM1,b);
sleep(1);
}
return 0;
}
```
运行后可以看到,当从一个 ringbuffer 切换到另一个 ringbuffer 写入的时候,head,count 都会从上一次结束的位置开始计数,这就是符合我们预期的:
接下来,我们再看一下用新定义的 push 方式进行写入,即传入的是 ringbuffer 变量:
```C
void* Producer_Pthread() {
while (keep_running) {
for (int i = 0; i < WRITE_NUM; i++) {
a[i] = a[i] + i;
}
// VERY IMPORTANT HERE TO USE THE ADDRESS OF RINGBUFFER !!!
ring_buffer_push_test(ringbuffer, WRITE_NUM, a);
sleep(1);
for (int i=0; i< WRITE_NUM1;i++){
b[i] = b[i]+i;
}
ring_buffer_push_test(ringbuffer1,WRITE_NUM1,b);
sleep(1);
}
return 0;
}
```
运行后可以看到输出结果不符合预期,每次从一个 ringbuffer 切到另一个 ringbuffer 写入的时候,head,count 都会从 0 开始,也就失去了 ringbuffer 的意义。因此这也就是为什么多次调用时,我们需要传入地址,而非变量。