fifo.h
---------------------------------------------------------------------------------------------------------
#ifndef FIFO_H
#define FIFO_H
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(1)
typedef struct{
char* buffer;
int buffer_size;
int count;
int write_ptr;
int read_ptr;
pthread_mutex_t mutex;
}tFifo,*pFifo;
#pragma pack()
int fifo_init(pFifo pfifo);
void fifo_uninit(pFifo pfifo);
int fifo_into(pFifo pfifo,char* buffer,int buffer_size);
char *fifo_get(pFifo pfifo,int* out_len);
int fifo_remove(pFifo pfifo);
#ifdef __cplusplus
}
#endif
#endif
fifo.c
---------------------------------------------------------------------------------------------------------
#include "fifo.h"
#include "../debug/debug.h"
#if 0
#define _debug_fifo
#endif
#ifdef _debug_fifo
#define debug_fifo(fmt,...) debug(fmt,##__VA_ARGS__)
#else
#define debug_fifo(fmt,...)
#endif
#if 1
#define FIFO_USE_MUTEX
#endif
#define FIFO_NODE_INVALID 0xFF
#define FIFO_NODE_VALID 0x00
#pragma pack(1)
typedef struct{
char flag;
int len;
}tNodeHead,*pNodeHead;
#pragma pack()
int fifo_init(pFifo pfifo)
{
debug_fifo("/n");
if(pfifo==NULL){
return -1;
}
pfifo->count = 0;
pfifo->read_ptr = 0;
pfifo->write_ptr = 0;
return 0;
}
void fifo_uninit(pFifo pfifo)
{
debug_fifo("/n");
return;
}
static int fifo_check_spare(pFifo pfifo,int need_len)
{
debug_fifo("/n");
int spare = 0;
if(pfifo->write_ptr >= pfifo->read_ptr)
{
spare = pfifo->buffer_size - pfifo->write_ptr;
if(need_len > spare)
{
if(pfifo->read_ptr > need_len){
if(spare>0){
pfifo->buffer[pfifo->write_ptr] = FIFO_NODE_INVALID;
}
spare = pfifo->read_ptr;
}else
spare = -1;
}
}else
{
spare = pfifo->read_ptr - pfifo->write_ptr;
}
if( spare == 0 )
return pfifo->buffer_size;
else if( spare >= need_len )
return spare;
return -1;
}
#define check_write_ptr(){/
if(pfifo->write_ptr>=pfifo->buffer_size || pfifo->buffer[pfifo->write_ptr]==FIFO_NODE_INVALID){/
debug_fifo("reset write_ptr=0/n");/
pfifo->write_ptr = 0;/
}/
}
int fifo_into(pFifo pfifo,char* buffer,int buffer_size)
{
debug_fifo("/n");
int retval = -1;
#ifdef FIFO_USE_MUTEX
pthread_mutex_lock(&(pfifo->mutex));
#endif
if(buffer==0||buffer_size<=0){
debug_warning("buffer is null/n");
goto error;
}
debug_fifo("begin read_ptr=%d,write_ptr=%d/n",pfifo->read_ptr,pfifo->write_ptr);
int node_head_len = sizeof(tNodeHead);
int need_size = node_head_len + buffer_size;
int spare=fifo_check_spare(pfifo,need_size);
debug_fifo("spare=%d/n",spare);
if(spare < 0)
{
debug_error("task buffer so busy,spare=%d,node head len=%d,need_len=%d/n",spare,node_head_len,need_size);
goto error;
}
check_write_ptr();
pNodeHead pHead = pfifo->buffer + pfifo->write_ptr;
pHead->flag = FIFO_NODE_VALID;
pHead->len = need_size;
char* pdata = ((char*)pHead) + node_head_len;
memcpy(pdata,buffer,buffer_size);
pfifo->write_ptr += need_size;
debug_fifo("end read_ptr=%d,write_ptr=%d/n",pfifo->read_ptr,pfifo->write_ptr);
pfifo->count++;
retval=pfifo->count;
debug_fifo("task post ok,read_ptr=%d,write_ptr=%d,write len=%d,count=%d/n",pfifo->read_ptr,pfifo->write_ptr,need_size,pfifo->count);
#if 0
int i;
debug("data=");
for(i=0;i<need_size+0x10;i++)
{
debugf("0x%02x ",((char*)pHead)[i]);
if(i==need_size-1)
debugf(" ~ ");
}
debugf("/n");
#endif
error:
#ifdef FIFO_USE_MUTEX
pthread_mutex_unlock(&(pfifo->mutex));
#endif
return retval;
}
static int fifo_is_empty(pFifo pfifo)
{
debug_fifo("/n");
int retval=0;
if(pfifo->write_ptr==pfifo->read_ptr)
retval=1;
return retval;
}
#define check_read_ptr(){/
if(pfifo->read_ptr>=pfifo->buffer_size || pfifo->buffer[pfifo->read_ptr]==FIFO_NODE_INVALID){/
debug_fifo("reset read_ptr=0/n");/
pfifo->read_ptr = 0;/
}/
}
char* fifo_get(pFifo pfifo,int* out_len)
{
debug_fifo("/n");
#ifdef FIFO_USE_MUTEX
pthread_mutex_lock(&(pfifo->mutex));
#endif
char* retval = NULL;
if(!fifo_is_empty(pfifo))
{
check_read_ptr();
int node_head_len = sizeof(tNodeHead);
pNodeHead pHead = (pNodeHead)(pfifo->buffer + pfifo->read_ptr);
retval = ((char*)pHead) + node_head_len;
int outlen = pHead->len - node_head_len;
if(out_len!=NULL){
*out_len = outlen;
}
#if 1
debug_fifo("task get ok,read_ptr=%d,write_ptr=%d,read len=%d,out len=%d,count=%d/n",pfifo->read_ptr,pfifo->write_ptr,pHead->len,outlen,pfifo->count);
#endif
}
#ifdef FIFO_USE_MUTEX
pthread_mutex_unlock(&(pfifo->mutex));
#endif
return retval;
}
int fifo_remove(pFifo pfifo)
{
debug_fifo("/n");
int retval = -1;
#ifdef FIFO_USE_MUTEX
pthread_mutex_lock(&(pfifo->mutex));
#endif
if(!fifo_is_empty(pfifo))
{
debug_fifo("task remove begin,read_ptr=%d,write_ptr=%d,count=%d/n",pfifo->read_ptr,pfifo->write_ptr,pfifo->count);
check_read_ptr();
pNodeHead pHead = (pNodeHead)(pfifo->buffer + pfifo->read_ptr);
int node_size = pHead->len;
pfifo->read_ptr += node_size;
pfifo->count--;
retval = pfifo->count;
#if 1
debug_fifo("task remove ok,read_ptr=%d,write_ptr=%d,remove len=%d,count=%d/n",pfifo->read_ptr,pfifo->write_ptr,node_size,pfifo->count);
#endif
}
#ifdef FIFO_USE_MUTEX
pthread_mutex_unlock(&(pfifo->mutex));
#endif
return retval;
}