代码中有相关注释:
// 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);
}
}
}