C语言 类面向对象 无锁 环形缓冲 ring_buffer

为类似面向对象,因为不能隐性传参,对象的方法必须把对象本身传入。
上代码
ring_buffer.c

/* File Info 
 * Author:      Holy.Han 
 * CreateTime:  2020/7/18 下午11:39:51 
 * LastEditor:  Holy.Han 
 * ModifyTime:  2020/7/18 下午11:39:54 
 * Description: 
*/
#include "ring_buffer.h"
#include 

typedef struct
{
	uint8_t *buffer;	   //存放实际的数据
	uint32_t read_offset;  //读取地址相对buffer的偏移量
	uint32_t write_offset; //写入地址相对buffer的偏移量
	uint32_t valid_size;   //buffer的有效size
	uint32_t total_size;   //buffer的总大小,即init时malloc的size
} ring_buf_t;

typedef struct
{
	ring_buf_t ring_buf;
	ring_t ring;
} ring_obj_t;

static void ring_destroy(ring_t *ring);
static void ring_write(ring_t *ring, void *write, uint32_t size);
static void ring_read(ring_t *ring, void *read, uint32_t size);
static uint32_t ring_valid(ring_t *ring);

static void ring_print(const char *str, uint8_t *data, uint32_t len)
{
	printf("%s:\r\n\t{ ", str);
	for (uint32_t i = 0; i < len; i++)
	{
		if (i == (len - 1))
		{
			printf("0x%02X", *(data + i));
		}
		else
		{
			printf("0x%02X, ", *(data + i));
		}
		if (i % 16 == 15 && i != (len - 1))
		{
			printf("\r\n\t  ");
		}
	}
	printf(" }\r\n");
}

ring_t *new_ring(uint32_t size)
{
	ring_obj_t *ring_obj = NULL;

	ring_obj = ring_alloc(sizeof(ring_obj_t));
	if (ring_obj == NULL)
	{
		return NULL;
	}
#if DBG_ENBALE
	printf("new ring addr=0x%p\r\n", ring_obj);
#endif
	ring_obj->ring_buf.buffer = ring_alloc(size);
	if (ring_obj->ring_buf.buffer == NULL)
	{
		ring_free(ring_obj);
		return NULL;
	}
#if DBG_ENBALE
	printf("ring 0x%p buffer addr=0x%p, size=%d\r\n", ring_obj, ring_obj->ring_buf.buffer, size);
#endif
	ring_obj->ring_buf.total_size = size;
	ring_obj->ring.destroy = ring_destroy;
	ring_obj->ring.write = ring_write;
	ring_obj->ring.read = ring_read;
	ring_obj->ring.valid = ring_valid;
#if DBG_ENBALE
	printf("ring 0x%p func addr=0x%p\r\n", ring_obj, ring_obj->ring);
#endif
	return &ring_obj->ring;
}

static void ring_destroy(ring_t *ring)
{
	if (ring == NULL)
	{
		return;
	}
	ring_obj_t *ring_obj = (ring_obj_t *)(((ring_buf_t *)ring) - 1);
	if (ring_obj->ring_buf.buffer != NULL)
	{
		ring_free(ring_obj->ring_buf.buffer);
	}
	ring_free(ring_obj);
#if DBG_ENBALE
	printf("destroy ring=0x%p\r\n", ring_obj);
#endif
}

static void ring_write(ring_t *ring, void *write, uint32_t size)
{
	if (ring == NULL || write == NULL)
	{
		return;
	}
#if DBG_ENBALE
	ring_print("ring write", (uint8_t *)write, size);
#endif
	ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);

	uint32_t write_offset = ring_buffer->write_offset;
	uint32_t total_size = ring_buffer->total_size;
	uint32_t first_write_size = 0;

	if (ring_buffer->valid_size + size > total_size) //ring_buffer->buffer未使用的总大小比需要写入的size小
	{
		// todo printf
		return;
	}

	if (size + write_offset <= total_size) //ring_buffer->buffer的后段未写入的空间不小于size
	{
		memcpy(ring_buffer->buffer + write_offset, write, size);
	}
	else //ring_buffer->buffer的后段未写入的空间小于size,这时候需要先在后面写入一部分,然后返回头部,从前面接着写入
	{
		first_write_size = total_size - write_offset;
		memcpy(ring_buffer->buffer + write_offset, write, first_write_size);
		memcpy(ring_buffer->buffer, (const uint8_t *)write + first_write_size, size - first_write_size);
	}
	ring_buffer->write_offset += size;
	ring_buffer->write_offset %= total_size;
	ring_buffer->valid_size += size;
#if DBG_ENBALE
	ring_print("ring now", (uint8_t *)(ring_buffer->buffer), ring_buffer->valid_size);
#endif
}

static void ring_read(ring_t *ring, void *read, uint32_t size)
{
	if (ring == NULL || read == NULL || size == 0)
	{
		return;
	}
	ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);

	uint32_t read_offset = ring_buffer->read_offset;
	uint32_t total_size = ring_buffer->total_size;
	uint32_t first_read_size = 0;

	if (size > ring_buffer->valid_size)
	{
		//todo print
		return;
	}

	if (total_size - read_offset >= size)
	{
		memcpy(read, ring_buffer->buffer + read_offset, size);
	}
	else
	{
		first_read_size = total_size - read_offset;
		memcpy(read, ring_buffer->buffer + read_offset, first_read_size);
		memcpy((uint8_t *)read + first_read_size, ring_buffer->buffer, size - first_read_size);
	}
#if DBG_ENBALE
	ring_print("ring read", (uint8_t *)read, size);
#endif
	ring_buffer->read_offset += size;
	ring_buffer->read_offset %= total_size;
	ring_buffer->valid_size -= size;
#if DBG_ENBALE
	ring_print("ring now", (uint8_t *)(ring_buffer->buffer), ring_buffer->valid_size);
#endif
}
static uint32_t ring_valid(ring_t *ring)
{
	if (ring == NULL)
	{
		return 0;
	}
	ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);
	return ring_buffer->valid_size;
}

最重要的头文件
ring_buffer.h

/* File Info 
 * Author:      Holy.Han 
 * CreateTime:  2020/7/18 下午11:40:15 
 * LastEditor:  Holy.Han 
 * ModifyTime:  2020/7/18 下午11:40:18 
 * Description: 
*/
#ifndef _RING_BUFFER_H
#define _RING_BUFFER_H

#include 
#include 
#include 

/*     */
#define ring_alloc(size) calloc(1, size)
#define ring_free(p) free(p)

#define DBG_ENBALE 1

struct ring
{
	void (*destroy)(struct ring *);
	void (*write)(struct ring *, void *, uint32_t);
	void (*read)(struct ring *, void *, uint32_t);
	uint32_t (*valid)(struct ring *);
};
typedef struct ring ring_t;

ring_t *new_ring(uint32_t size);

#endif /* _RING_BUFFER_H */

demo.c

#include 
#include "utils\ring_buffer.h"

int main(int argc, char **argv)
{
	uint8_t write[40];
	uint8_t read[100];
	for (size_t i = 0; i < 16; i++)
	{
		write[i] = i + '0';
	}

	ring_t *myring = new_ring(128);
	myring->write(myring, write, 16);
	for (size_t i = 0; i < 32; i++)
	{
		write[i] = i + 'a';
	}
	myring->write(myring, write, 32);
	uint32_t size = myring->valid(myring);
	myring->read(myring, read, size);
	myring->destroy(myring);
	return 0;
}

你可能感兴趣的:(C语言)