Ring memory pool ring_buffer in webrtc

In the previous C++ article, the ring memory pool was mentioned at the time;

There is an implementation of a ring memory pool in webrtc, ring_buffer;


Talk about the implementation logic and characteristics:

1: very good

2: Implemented in C language, it can be simply encapsulated as class in C++;

3: A continuous piece of memory is opened on the heap; after confirmation, the size cannot be changed;

     If you want to achieve dynamic memory size changes, there are two ways:

     (3.1): Add an implementation function yourself; a little troublesome;

            You can directly change the memory size realloc just created:

              There are three situations when realloc expands the memory:
            1) If there is a required memory space behind the current memory segment, then directly expand this memory space, and realloc() will return the original pointer.
            2) If the free bytes behind the current memory segment are not enough, use the first memory block in the heap that can meet this requirement, copy the current data to the new location, and release the original data block, Returns the new memory block location.

            3) If the application fails, it will return NULL, at this time, the original pointer is still valid


           Or, directly malloc a new memory, copy the previous content, and release it;

                 

    (3.2): When the memory size needs to be changed (usually it needs to be increased), a new ring_buffer object is created, the size is specified, and the previous content and read and write positions are copied to the new object; simpler;

                 Read the data through read_buffer, and then write_buffer the data to the new ring_buffer, so that's it;


4: When writing data, when the write pos is full and there is no read buffer, the data will not continue to be written, and the previous data will not be overwritten;


5: When the data is full, after reading the buffer, you can continue to write the buffer, and the size that can be written is the size of the data just read;


6: Assume that the init size is 100 bytes, then write 10 bytes, read 5 bytes, and continue to write 10 bytes, of course, it will be stored continuously in memory;



Source file location: src\common_audio\ring_buffer.h


Take a look at the header file first:

/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */


// A ring buffer to hold arbitrary data. Provides no thread safety. Unless
// otherwise specified, functions return 0 on success and -1 on error.


#ifndef COMMON_AUDIO_RING_BUFFER_H_
#define COMMON_AUDIO_RING_BUFFER_H_


#ifdef __cplusplus
extern "C" {
#endif


#include <stddef.h>  // size_t


enum Wrap { SAME_WRAP, DIFF_WRAP };


typedef struct RingBuffer {
  size_t read_pos;
  size_t write_pos;
  size_t element_count;
  size_t element_size;
  enum Wrap rw_wrap;
  char* data;
} RingBuffer;


// Creates and initializes the buffer. Returns null on failure.
RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size);
void WebRtc_InitBuffer(RingBuffer* handle);
void WebRtc_FreeBuffer(void* handle);


// Reads data from the buffer. Returns the number of elements that were read.
// The |data_ptr| will point to the address where the read data is located.
// If no data can be read, |data_ptr| is set to |NULL|. If all data can be read
// without buffer wrap around then |data_ptr| will point to the location in the
// buffer. Otherwise, the data will be copied to |data| (memory allocation done
// by the user) and |data_ptr| points to the address of |data|. |data_ptr| is
// only guaranteed to be valid until the next call to WebRtc_WriteBuffer().
//
// To force a copying to |data|, pass a null |data_ptr|.
//
// Returns number of elements read.
size_t WebRtc_ReadBuffer(RingBuffer* handle,
                         void** data_ptr,
                         void* data,
                         size_t element_count);


// Writes |data| to buffer and returns the number of elements written.
size_t WebRtc_WriteBuffer(RingBuffer* handle, const void* data,
                          size_t element_count);


// Moves the buffer read position and returns the number of elements moved.
// Positive |element_count| moves the read position towards the write position,
// that is, flushing the buffer. Negative |element_count| moves the read
// position away from the the write position, that is, stuffing the buffer.
// Returns number of elements moved.
int WebRtc_MoveReadPtr(RingBuffer* handle, int element_count);


// Returns number of available elements to read.
size_t WebRtc_available_read(const RingBuffer* handle);


// Returns number of available elements for write.
size_t WebRtc_available_write(const RingBuffer* handle);


#ifdef __cplusplus
}
#endif


#endif  // COMMON_AUDIO_RING_BUFFER_H_




Write an example simple test:

#include "ring_buffer.h"


#include <iostream>
#include <string>


class MyClassRingBuffer
{
public:
MyClassRingBuffer()
{
m_pRingBuffer = WebRtc_CreateBuffer(100, 1);


WebRtc_InitBuffer(m_pRingBuffer); 


}


~MyClassRingBuffer()
{


WebRtc_FreeBuffer(m_pRingBuffer);
}




public:
void output1(char * pchar, int n)
{
for (int b = 0; b < n; b++)
{
int n = int(pchar[b]);


std::string str = std::to_string(n);






OutputDebugStringA(str.c_str());


OutputDebugStringA("\n");


}


OutputDebugStringA("------------------------------------------\n");}




public:


RingBuffer * m_pRingBuffer;




void test_WriteBuffer(int n)
{
for (int b = 0; b < n; b++)
{
WebRtc_WriteBuffer(m_pRingBuffer, &b, 1);
}
}








void test_element_count()
{
//直接获取环形内存中的所有数据,不考虑读写位置变量;
output1(m_pRingBuffer->data, m_pRingBuffer->element_count);}void test_read_pos(){output1(m_pRingBuffer->data, m_pRingBuffer->read_pos);}void test_write_pos(){output1(m_pRingBuffer->data, m_pRingBuffer->write_pos);}void test_ReadBuffer(int n)static char * pReadBuf_r = new char[100];memset(pReadBuf_r, 0, 100);
























 













 

WebRtc_ReadBuffer(m_pRingBuffer, nullptr, pReadBuf_r, n);




output1(pReadBuf_r, n);


}


};




MyClassRingBuffer MyClassRingBufferObj;


void CMFCApplication2Dlg::OnBnClickedButton1()
{
// TODO: add control notification handler code here MyClassRingBufferObj.test_WriteBuffer(100) ;  MyClassRingBufferObj.test_element_count(); } void CMFCApplication2Dlg::OnBnClickedButton2() { // TODO: add control notification handler code here MyClassRingBufferObj.test_ReadBuffer(10); } void CMFCApplication2Dlg::OnBnClickedButton3() { // TODO: here Add control notification handler code static int n = 1; MyClassRingBufferObj.test_WriteBuffer(n++); }









































There is also an article here that introduces two ring_buffers:

Mainly explains the implementation in liblcthw (" Learn C The Hard Way " );

The website of the open source library liblcthw is   https://github.com/zedshaw/liblcthw . It   implements some common data structures, list, map, tree, string function, ring buffer, etc. in C code. It is worth watching for those who learn C language. Look.   

from: https://blog.csdn.net/langeldep/article/details/8888582


You can search for a lot of "ring buffer" open source projects on GitHub, but I still feel that the implementation in webrtc is very simple and excellent, and can be modified according to your own needs;




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324525606&siteId=291194637