Список содержимого

Циклический буфер

Не самая красивая реализация буфера. Мне самому он не нравится, поэтому и выкладываю :-)

Для формирования используется финт ушами из макроса DECLARE_CIRC_BUFFER(). Первый параметр переменная для буфера, второй - размер буфера в байтах. Очень важно чтобы размер был кратен степени двойки, то бишь 4,8,16,32 и т.д. Преимущество данного метода меньше писанины в клиентском коде, из недостатков - накладные расходы на вызов функций и неконстантность SizeMask.

example

См. также аппаратный уарт

#include "circ_buf.h"
 
#define MY_BUFFER_SIZE (32)
#if (MY_BUFFER_SIZE & (MY_BUFFER_SIZE-1))
#error MY_BUFFER_SIZE must be power of 2
#endif
 
 
  DECLARE_CIRC_BUFFER( buf, MY_BUFFER_SIZE );
 
  circ_Init(&buf.b);
  while( circ_Put( &buf.b, '1' ) != 0 ) continue;
  print( circ_Get( &buf.b ) );

h-file

/**
* @file	circ_buf.h
* @brief Circular Buffer
*
* @author      Rustem Kalimullin
* @par E-mail:
*              hellos@mail.ru
* @par Copyright:
*              (c) Kurt, 2006
*/
 
#ifndef KR_CIRCBUF_INC_H_
#define KR_CIRCBUF_INC_H_
 
typedef struct circ_buffer_t {
	volatile unsigned int Get;
	volatile unsigned int Put;
	unsigned int SizeMask;
	unsigned char Buffer[0];
} circ_buffer_t;
 
 
#define DECLARE_CIRC_BUFFER(name,size) \
struct {\
	circ_buffer_t b;\
	unsigned char name##pad[ size-0 ];\
} name = { 0, 0, size-1 };
 
 
int circ_Get( circ_buffer_t * p );
int circ_Put( circ_buffer_t * p, unsigned char data );
 
void circ_Init( circ_buffer_t * p );
int circ_HasSpace( circ_buffer_t * p );
int circ_HasData( circ_buffer_t * p );
 
 
#endif

c-file

/**
* @file	circ_buf.c
* @brief Circular Buffer
*
* @author      Rustem Kalimullin
* @par E-mail:
*              hellos@mail.ru
* @par Copyright:
*              (c) Kurt, 2006
*/
 
#include "common.h"
#include "circ_buf.h"
 
//---------------------------------------------------------
//! Get byte from buffer
//! @return -1 if failed
int circ_Get( circ_buffer_t * p )
{
	unsigned int t = p->Get;
	if ( t != p->Put ) {
		p->Get = t+1 &  p->SizeMask;
		return p->Buffer[t];
	}
	return -1;  
}
 
 
//---------------------------------------------------------
//! Put byte to buffer
//! @return -1 if failed
int circ_Put( circ_buffer_t * p, unsigned char data )
{
	unsigned int t = p->Put+1 &  p->SizeMask;
	if( t != p->Get ) {
		p->Buffer[p->Put] = data;
		p->Put = t;
		return 0;
	}
	return -1;
}
 
//---------------------------------------------------------
//! Init buffer
void circ_Init( circ_buffer_t * p )
{
	p->Get = p->Put = 0;   
}
 
//---------------------------------------------------------
int circ_HasSpace( circ_buffer_t * p )
{
	unsigned int t = ( (p->Put + 1) &  p->SizeMask );
	return ( t != p->Get );
}
 
//---------------------------------------------------------
int circ_HasData( circ_buffer_t * p )
{
	unsigned int t = p->Get;
	return ( t != p->Put );
}
 
sources/circ_buf.txt · Последние изменения: 2021/10/09 14:22 kurt