一个环形缓冲(ringbuf)的简单实现

代码中有相关注释:

// mybuf.h

#ifndef _RINGBUF_HEADER_
#define _RINGBUF_HEADER_
#ifdef _cplusplus
extern "C"{
#endif

/*************
 1  === succeed
 0  === failed
*************/

typedef struct _ringbuf_ ringbuf;
/******************
  申请的缓冲的大小
  size 为缓冲的大小
 ****************/
ringbuf* ringbuf_create(unsigned int size);

/*************
  往缓冲中放数据

 ****************/

int ringbuf_push(ringbuf* pbuf,const void* data,int size);

/***************
  从缓冲中取数据
 *****************/
int ringbuf_pop(ringbuf* pbuf,void* data,int size);

/*************
从缓冲中取数据 但是不修改缓冲的大小
************/
void* ringbuf_top(ringbuf* pbuf,void* data,int size);

/*******************
移动缓冲的头指针

****************/
int ringbuf_head_move(ringbuf* pbuf,int size);

/***************
如果 size > 0 就是 上面的这个函数
其中size < 0 也是可以的
*************************/

int ringbuf_head_seek(ringbuf* pbuf,int size);

/***************
重新申请缓冲的大小
size 的大小是的最终大小
*******************/
ringbuf* ringbuf_realloc(ringbuf* pbuf,int size);

/*****************
获得buf的大小
******************/
int ringbuf_get_size(ringbuf* pbuf);

/***************
获得缓冲的开始
**************/

#if 1 
void* ringbuf_get_head(ringbuf* pbuf);

/****************
获得当前缓冲的尾部
****************/
void* ringbuf_get_tail(ringbuf* pbuf);


/***************
  销毁缓冲区
 *********************/
void ringbuf_destroy(ringbuf* pbuf);
#endif


#ifdef _cplusplus
}
#endif


#endif

// mybuf.c
#include 
#include 
#include 
#include 
#include "mybuf.h"
#define RINGBUF_START(pbuf) ((unsigned char*)(pbuf->buf_start))
#define RINGBUF_END(pbuf) (pbuf->buf_start+pbuf->buf_size-1)
#define RINGBUF_HEAD(pbuf) (pbuf->buf_head)
#define RINGBUF_TAIL(pbuf) (pbuf->buf_tail)
#define RINGBUF_SIZE(pbuf) (pbuf->buf_size)
#define RINGBUF_USED(pbuf)	(RINGBUF_HEAD(pbuf) <= RINGBUF_TAIL(pbuf) ? RINGBUF_TAIL(pbuf) - RINGBUF_HEAD(pbuf) : RINGBUF_SIZE(pbuf)+RINGBUF_TAIL(pbuf)-RINGBUF_HEAD(pbuf))

#define RINGBUF_FREE(pbuf) (RINGBUF_HEAD(pbuf) <= RINGBUF_TAIL(pbuf) ? RINGBUF_SIZE(pbuf)+RINGBUF_HEAD(pbuf) - RINGBUF_TAIL(pbuf) : RINGBUF_HEAD(pbuf) - RINGBUF_TAIL(pbuf))

struct _ringbuf_
{
	pthread_mutex_t mutex;
	unsigned int buf_size;
	unsigned char* buf_head;
	unsigned char* buf_tail;
	unsigned char buf_start[1];
};

ringbuf* ringbuf_create(unsigned int size)
{
	if(size > 0)
	{
		ringbuf *buf = malloc(sizeof(ringbuf) + size);
		if(buf == NULL)
		{
			return NULL;
		}
		buf->buf_size = size;
		buf->buf_head = buf->buf_tail = buf->buf_start;
		pthread_mutex_init(&buf->mutex,NULL);
		return buf;
	}
	return NULL;
}
int ringbuf_used(ringbuf* buf)
{
	int buf_used;
	pthread_mutex_lock(&buf->mutex);
	if(buf->buf_head <= buf->buf_tail)
	{
		buf_used = buf->buf_tail - buf->buf_head;
	}
	else
	{
		buf_used = buf->buf_size+buf->buf_tail - buf->buf_head;
	}
	pthread_mutex_unlock(&buf->mutex);
	return buf_used;
}
int ringbuf_free(ringbuf* buf)
{
	int buf_free;

	pthread_mutex_lock(&buf->mutex);
	if(buf->buf_head <= buf->buf_tail )
	{
		buf_free = buf->buf_size+buf->buf_head - buf->buf_tail;
	}
	else
	{
		buf_free =  buf->buf_head - buf->buf_tail;
	}
	pthread_mutex_unlock(&buf->mutex);
	return buf_free;
}
int ringbuf_push(ringbuf* pbuf,const void* data,int size)
{
	pthread_mutex_lock(&pbuf->mutex);
	if(pbuf && data && size > 0 && size < (int)RINGBUF_FREE(pbuf))
	{
		unsigned int tail_free = RINGBUF_END(pbuf) - RINGBUF_TAIL(pbuf) + 1;
		if(tail_free >= size)
		{
			memcpy(RINGBUF_TAIL(pbuf),(char*)data,size);
			RINGBUF_TAIL(pbuf) += size;
			if(RINGBUF_TAIL(pbuf) > RINGBUF_END(pbuf) )
				RINGBUF_TAIL(pbuf) = RINGBUF_START(pbuf);
		}
		else
		{
			memcpy(RINGBUF_TAIL(pbuf),(char*)data,tail_free);
			unsigned int lev = size - tail_free;
			memcpy(RINGBUF_START(pbuf),(char*)data+tail_free,lev);
			RINGBUF_TAIL(pbuf) = RINGBUF_START(pbuf) + lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	pthread_mutex_unlock(&pbuf->mutex);
	return 0; //失败

}

int ringbuf_pop(ringbuf* pbuf,void* data,int size)
{
	pthread_mutex_lock(&pbuf->mutex);
	if(pbuf && data && size > 0 && size < (int)RINGBUF_USED(pbuf) )
	{
		unsigned int head_used = RINGBUF_END(pbuf) - RINGBUF_HEAD(pbuf) + 1;
		if(head_used >= size)
		{
			memcpy((char*)data,RINGBUF_HEAD(pbuf),size);
			RINGBUF_HEAD(pbuf) += size;
			if(RINGBUF_HEAD(pbuf) > RINGBUF_END(pbuf))
				RINGBUF_HEAD(pbuf) = RINGBUF_START(pbuf);
		}
		else
		{
			memcpy((char*)data,RINGBUF_HEAD(pbuf),head_used);
			unsigned int lev = size - head_used;
			memcpy((char*)data+head_used,RINGBUF_START(pbuf),lev);
			RINGBUF_HEAD(pbuf) = RINGBUF_START(pbuf) + lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;// succeed
	}
	pthread_mutex_unlock(&pbuf->mutex);
	return 0; // failed

}

void ringbuf_destroy(ringbuf* pbuf)
{
	free(pbuf);
}

void ringbuf_clear(ringbuf* pbuf)
{
	pthread_mutex_lock(&pbuf->mutex);
	RINGBUF_HEAD(pbuf) = RINGBUF_TAIL(pbuf) = RINGBUF_START(pbuf);
	pthread_mutex_unlock(&pbuf->mutex);
}

void* ringbuf_top(ringbuf* pbuf,void* data,int size)
{
	pthread_mutex_lock(&pbuf->mutex);
	if( pbuf && data && size > 0 && size <= (int)RINGBUF_USED(pbuf))
	{
		unsigned int head_used = RINGBUF_END(pbuf) - RINGBUF_HEAD(pbuf)+ 1;
		if(head_used >= size)
		{
			data = RINGBUF_HEAD(pbuf);
		}
		else
		{
			memcpy((char*)data,RINGBUF_HEAD(pbuf),head_used);
			unsigned int lev = size - head_used;
			memcpy((char*)data+head_used,RINGBUF_START(pbuf),lev);
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return data;
	}
	pthread_mutex_unlock(&pbuf->mutex);
	return NULL;
}

int  ringbuf_head_move(ringbuf* pbuf,int size)
{

	pthread_mutex_lock(&pbuf->mutex);
	if(pbuf && size > 0 && size <= (int)RINGBUF_USED(pbuf))
	{
		unsigned int head_used = RINGBUF_END(pbuf)-RINGBUF_HEAD(pbuf)+ 1;
		if( head_used >= size)
		{
			RINGBUF_HEAD(pbuf) += size;
			if(RINGBUF_HEAD(pbuf) > RINGBUF_END(pbuf))
				RINGBUF_HEAD(pbuf) = RINGBUF_HEAD(pbuf);
		}
		else
		{
			unsigned int lev = size - head_used;
			RINGBUF_HEAD(pbuf) = RINGBUF_START(pbuf) + lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	pthread_mutex_unlock(&pbuf->mutex);
	return 0;
}

int ringbuf_head_seek(ringbuf* pbuf,int  offset)
{
	if(offset >= 0)
	{

		pthread_mutex_lock(&pbuf->mutex);
		unsigned int head_used = RINGBUF_END(pbuf) - RINGBUF_HEAD(pbuf)+1;
		if( offset <= head_used )
		{
			RINGBUF_HEAD(pbuf) += offset;
		}
		else
		{
			unsigned int lev = offset - head_used;
			RINGBUF_HEAD(pbuf) = RINGBUF_START(pbuf) + lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	else
	{

		pthread_mutex_lock(&pbuf->mutex);
		unsigned int head_free = RINGBUF_HEAD(pbuf) - RINGBUF_START(pbuf) + 1;
		if( -offset <= head_free )
		{
			RINGBUF_HEAD(pbuf) += offset;
		}
		else
		{
			unsigned int lev = -(offset + head_free);
			RINGBUF_HEAD(pbuf) = RINGBUF_END(pbuf) - lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	return 0;
}

int ringbuf_head_free(ringbuf* pbuf)
{
	unsigned int ret;
	pthread_mutex_lock(&pbuf->mutex);
	ret = RINGBUF_HEAD(pbuf) - RINGBUF_START(pbuf);
	pthread_mutex_unlock(&pbuf->mutex);
	return ret;
}
int ringbuf_tail_seek(ringbuf* pbuf,int offset)
{
	if(offset >= 0)
	{

		pthread_mutex_lock(&pbuf->mutex);
		unsigned int tail_free = RINGBUF_END(pbuf) - RINGBUF_TAIL(pbuf) + 1;
		if(offset <= tail_free)
		{
			RINGBUF_TAIL(pbuf) += offset;
		}
		else
		{
			unsigned int lev = offset - tail_free;
			RINGBUF_TAIL(pbuf) = RINGBUF_START(pbuf) + lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	else
	{

		pthread_mutex_lock(&pbuf->mutex);
		unsigned int tail_free = RINGBUF_TAIL(pbuf) - RINGBUF_START(pbuf) + 1;
		if(-offset <= tail_free)
		{
			RINGBUF_TAIL(pbuf) += offset;
		}
		else
		{
			unsigned int lev = -(offset + tail_free);
			RINGBUF_TAIL(pbuf) = RINGBUF_END(pbuf) - lev;
		}
		pthread_mutex_unlock(&pbuf->mutex);
		return 1;
	}
	return 0;

}
int ringbuf_rewind(ringbuf* pbuf)
{

	unsigned char *start_tail = NULL;
	unsigned int head_free = ringbuf_head_free(pbuf);
	if(head_free == 0)
	{
		return 0;
	}

	pthread_mutex_lock(&pbuf->mutex);
	if( RINGBUF_HEAD(pbuf) <= RINGBUF_TAIL(pbuf) )
	{
		memmove(RINGBUF_START(pbuf), RINGBUF_HEAD(pbuf), RINGBUF_USED(pbuf));

	}
	else
	{
		unsigned int tail_used = RINGBUF_TAIL(pbuf) - RINGBUF_HEAD(pbuf) +1;
		unsigned int head_used = RINGBUF_END(pbuf) - RINGBUF_HEAD(pbuf) + 1;
		start_tail = malloc(sizeof(char)*tail_used + 1);
		if(start_tail == NULL)
		{
			return ;
		}
		memcpy(start_tail,RINGBUF_START(pbuf),tail_used);
		start_tail[tail_used] = '\0';
		memmove(RINGBUF_START(pbuf), RINGBUF_HEAD(pbuf), head_used);
		memmove(RINGBUF_START(pbuf)+head_used+1,start_tail,tail_used);
		RINGBUF_HEAD(pbuf) = RINGBUF_START(pbuf);
		RINGBUF_TAIL(pbuf) = RINGBUF_START(pbuf) + RINGBUF_USED(pbuf);
	}
	pthread_mutex_unlock(&pbuf->mutex);
	return 1;
}

// 重新申请ringbuf 这个大小是新生成的大小 而不是扩展的大小
ringbuf* ringbuf_realloc(ringbuf* pbuf,int size)
{
	pthread_mutex_lock(&pbuf->mutex);
	unsigned int init_size = RINGBUF_SIZE(pbuf);
	if( init_size == size)
	{
		pthread_mutex_unlock(&pbuf->mutex);
		return pbuf;
	}
	unsigned int tail_pos = RINGBUF_TAIL(pbuf) - RINGBUF_START(pbuf);
	if( tail_pos > size)
	{
		ringbuf_rewind(pbuf);
		tail_pos = RINGBUF_TAIL(pbuf) - RINGBUF_START(pbuf);
		size = tail_pos > size ? tail_pos : size;
	}
	unsigned int head_pos = RINGBUF_HEAD(pbuf) - RINGBUF_START(pbuf);
	ringbuf* new_buf = realloc(pbuf ,sizeof(ringbuf) + size);
	RINGBUF_SIZE(new_buf) = size;
	RINGBUF_HEAD(new_buf) = RINGBUF_START(new_buf) + head_pos;
	RINGBUF_TAIL(new_buf) = RINGBUF_START(new_buf) + tail_pos;
	pthread_mutex_unlock(&pbuf->mutex);
	return new_buf;
}

int  ringbuf_tail_free(ringbuf* pbuf)
{
	int ret;
	pthread_mutex_lock(&pbuf->mutex);
	ret = RINGBUF_END(pbuf) - RINGBUF_TAIL(pbuf) + 1;
	pthread_mutex_unlock(&pbuf->mutex);
	return ret;
}

void* ringbuf_get_head(ringbuf* pbuf)
{
	void* ret;

	pthread_mutex_lock(&pbuf->mutex);
	ret = RINGBUF_HEAD(pbuf);
	pthread_mutex_unlock(&pbuf->mutex);
	return ret;
}
void* ringbuf_get_tail(ringbuf* pbuf)
{
	void* ret;
	pthread_mutex_lock(&pbuf->mutex);
	ret = RINGBUF_TAIL(pbuf);
	pthread_mutex_unlock(&pbuf->mutex);
	return ret;
}

int ringbuf_get_size(ringbuf* pbuf)
{	
	int ret;
	pthread_mutex_lock(&pbuf->mutex);
	ret = RINGBUF_SIZE(pbuf);
	pthread_mutex_unlock(&pbuf->mutex);
	return ret;
}
#include 
#include 
#include 
#include 
#include "mybuf.h"

#define BUF_SIZE (1024)
void* thread_put(void* args);
void* thread_get(void* args);
pthread_mutex_t mutex;
pthread_cond_t cond;
int main()
{
	ringbuf* buf = NULL;
	char tm[64];
	memset(tm,0x00,sizeof(tm));
	pthread_t pid[2];
	int i,ret;
	buf= ringbuf_create(BUF_SIZE);
	pthread_cond_init(&cond,NULL);
	pthread_mutex_init(&mutex,NULL);
//	printf("buf start is %d end is %d\r\n",ringbuf_get_head(buf),ringbuf_get_tail(buf));
	printf("buf start is %d \r\n",ringbuf_get_head(buf));

#if	1 
	ret = pthread_create(&pid[i],NULL,thread_get,(void*)buf);
	if(ret!= 0)
	{
		printf("can not open \r\n");
	}
	ret = pthread_create(&pid[i],NULL,thread_put,(void*)buf);
	if(ret!= 0)
	{
		printf("can not open \r\n");
	}
	while(1)
	{
		sleep(4);
		printf("In \r\n");
		
		}

#endif
#if 0 
	strcpy(tm,"dsfaaa");
	ringbuf_push(buf,tm,strlen(tm));
	printf("buf size is %d\r\n",ringbuf_get_size(buf));
	
	memset(tm,0x00,sizeof(tm));
	ringbuf_pop(buf,tm,4);
	printf("from buf is %s\r\n",tm);
	ringbuf_destroy(buf);
#endif
	return 0;

}
void *thread_get(void* args)
{
	ringbuf *buf=(ringbuf*)args;
//	char *buf=(char*)args;
	char temp[100];
	memset(temp,0x00,sizeof(temp));
//	strcpy(temp,"wangguoxi");
	for(;;)
	{
		memset(temp,0x00,sizeof(temp));
		pthread_mutex_lock(&mutex);
		pthread_cond_wait(&cond,&mutex);
		ringbuf_pop(buf,temp,90);
//		strncpy(temp,buf,10);
		printf("start %d end is %d get is  %s \r\n",ringbuf_get_head(buf),ringbuf_get_tail(buf),temp);
		memset(buf,0x00,sizeof(buf));
		pthread_mutex_unlock(&mutex);
	}
}


void *thread_put(void* args)
{
	ringbuf *buf=(ringbuf*)args;
//	char *buf=(char*)args;
	int i;
	char temp[100];
	memset(temp,0x00,sizeof(temp));
	for(i=0;i<10;i++)
	strcpy(temp+i*9,"wangguoxi");
	printf("%s\r\n",temp);
	sleep(5);
	for(;;)
	{
		if(temp!=NULL)
		{

			pthread_mutex_lock(&mutex);
			ringbuf_push(buf,temp,strlen(temp));
			printf("head is %d\r\n",ringbuf_get_head(buf));
		//	strncpy(buf,temp,strlen(temp));
			pthread_mutex_unlock(&mutex);
			pthread_cond_signal(&cond);
//			sleep(1);
		usleep(1);
		}

	}
}





你可能感兴趣的:(linux网络编程)