Refactor ring_buffer interface, add a feature and a test.
* Add a RingBuffer typedef. * Add the ability to force a memcpy by passing a null ptr. In some cases, we know we want a memcpy. This allows us to skip a potential intermediate memcpy. * Add a stress test. Review URL: https://webrtc-codereview.appspot.com/1111004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3567 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -13,7 +13,7 @@
|
||||
|
||||
#include "ring_buffer.h"
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -22,21 +22,21 @@ enum Wrap {
|
||||
DIFF_WRAP
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct RingBuffer {
|
||||
size_t read_pos;
|
||||
size_t write_pos;
|
||||
size_t element_count;
|
||||
size_t element_size;
|
||||
enum Wrap rw_wrap;
|
||||
char* data;
|
||||
} buf_t;
|
||||
};
|
||||
|
||||
// Get address of region(s) from which we can read data.
|
||||
// If the region is contiguous, |data_ptr_bytes_2| will be zero.
|
||||
// If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
|
||||
// region. Returns room available to be read or |element_count|, whichever is
|
||||
// smaller.
|
||||
static size_t GetBufferReadRegions(buf_t* buf,
|
||||
static size_t GetBufferReadRegions(RingBuffer* buf,
|
||||
size_t element_count,
|
||||
void** data_ptr_1,
|
||||
size_t* data_ptr_bytes_1,
|
||||
@ -65,23 +65,25 @@ static size_t GetBufferReadRegions(buf_t* buf,
|
||||
return read_elements;
|
||||
}
|
||||
|
||||
int WebRtc_CreateBuffer(void** handle,
|
||||
int WebRtc_CreateBuffer(RingBuffer** handle,
|
||||
size_t element_count,
|
||||
size_t element_size) {
|
||||
buf_t* self = NULL;
|
||||
|
||||
if (handle == NULL) {
|
||||
RingBuffer* self = NULL;
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
if (element_count == 0 || element_size == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
self = malloc(sizeof(buf_t));
|
||||
if (self == NULL) {
|
||||
self = malloc(sizeof(RingBuffer));
|
||||
if (!self) {
|
||||
return -1;
|
||||
}
|
||||
*handle = self;
|
||||
|
||||
self->data = malloc(element_count * element_size);
|
||||
if (self->data == NULL) {
|
||||
if (!self->data) {
|
||||
free(self);
|
||||
self = NULL;
|
||||
return -1;
|
||||
@ -93,10 +95,8 @@ int WebRtc_CreateBuffer(void** handle,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtc_InitBuffer(void* handle) {
|
||||
buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
int WebRtc_InitBuffer(RingBuffer* self) {
|
||||
if (!self) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -110,35 +110,27 @@ int WebRtc_InitBuffer(void* handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtc_FreeBuffer(void* handle) {
|
||||
buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
return -1;
|
||||
void WebRtc_FreeBuffer(void* handle) {
|
||||
RingBuffer* self = (RingBuffer*)handle;
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(self->data);
|
||||
free(self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t WebRtc_ReadBuffer(void* handle,
|
||||
size_t WebRtc_ReadBuffer(RingBuffer* self,
|
||||
void** data_ptr,
|
||||
void* data,
|
||||
size_t element_count) {
|
||||
|
||||
buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (data_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
void* buf_ptr_1 = NULL;
|
||||
@ -157,33 +149,35 @@ size_t WebRtc_ReadBuffer(void* handle,
|
||||
// |data| and point to it.
|
||||
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
||||
memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2);
|
||||
*data_ptr = data;
|
||||
} else {
|
||||
buf_ptr_1 = data;
|
||||
} else if (!data_ptr) {
|
||||
// No wrap, but a memcpy was requested.
|
||||
memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
|
||||
}
|
||||
if (data_ptr) {
|
||||
// |buf_ptr_1| == |data| in the case of a wrap.
|
||||
*data_ptr = buf_ptr_1;
|
||||
}
|
||||
|
||||
// Update read position
|
||||
WebRtc_MoveReadPtr(handle, (int) read_count);
|
||||
WebRtc_MoveReadPtr(self, (int) read_count);
|
||||
|
||||
return read_count;
|
||||
}
|
||||
}
|
||||
|
||||
size_t WebRtc_WriteBuffer(void* handle,
|
||||
size_t WebRtc_WriteBuffer(RingBuffer* self,
|
||||
const void* data,
|
||||
size_t element_count) {
|
||||
|
||||
buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
if (data == NULL) {
|
||||
if (!data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
const size_t free_elements = WebRtc_available_write(handle);
|
||||
const size_t free_elements = WebRtc_available_write(self);
|
||||
const size_t write_elements = (free_elements < element_count ? free_elements
|
||||
: element_count);
|
||||
size_t n = write_elements;
|
||||
@ -206,19 +200,16 @@ size_t WebRtc_WriteBuffer(void* handle,
|
||||
}
|
||||
}
|
||||
|
||||
int WebRtc_MoveReadPtr(void* handle, int element_count) {
|
||||
|
||||
buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
int WebRtc_MoveReadPtr(RingBuffer* self, int element_count) {
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
// We need to be able to take care of negative changes, hence use "int"
|
||||
// instead of "size_t".
|
||||
const int free_elements = (int) WebRtc_available_write(handle);
|
||||
const int readable_elements = (int) WebRtc_available_read(handle);
|
||||
const int free_elements = (int) WebRtc_available_write(self);
|
||||
const int readable_elements = (int) WebRtc_available_read(self);
|
||||
int read_pos = (int) self->read_pos;
|
||||
|
||||
if (element_count > readable_elements) {
|
||||
@ -246,10 +237,8 @@ int WebRtc_MoveReadPtr(void* handle, int element_count) {
|
||||
}
|
||||
}
|
||||
|
||||
size_t WebRtc_available_read(const void* handle) {
|
||||
const buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
size_t WebRtc_available_read(const RingBuffer* self) {
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -260,12 +249,10 @@ size_t WebRtc_available_read(const void* handle) {
|
||||
}
|
||||
}
|
||||
|
||||
size_t WebRtc_available_write(const void* handle) {
|
||||
const buf_t* self = (buf_t*) handle;
|
||||
|
||||
if (self == NULL) {
|
||||
size_t WebRtc_available_write(const RingBuffer* self) {
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self->element_count - WebRtc_available_read(handle);
|
||||
return self->element_count - WebRtc_available_read(self);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user