简单的双缓冲区实现

来源:互联网 发布:js微信授权获取code 编辑:程序博客网 时间:2024/05/17 03:18

简单的双缓冲区实现

一、简述

在一些应用中可能需要用到双缓冲区,每个缓冲区有两种状态——可读的和可写的。当可写的缓冲区写满后转变为可读的,当可读的缓冲区数据全部被读取后转变为可写的。

二、实现

实现中使用了线程互斥量,保证各个操作是线程安全的。
/* doublebuffer.h starting */#ifndef __DOUBLE_BUFFER_H__#define __DOUBLE_BUFFER_H__#ifdef __cplusplusextern "C" {#endif#include <stdio.h>#include <stdlib.h>#include <pthread.h>#ifndef NULL#define NULL((void *)0)#endif#ifndef FAIL#define FAIL(-1)#endif#ifndef SUCC#define SUCC(0)#endif#ifndef TRUE#define TRUE(1)#endif#ifndef FALSE#define FALSE(0)#endif#define DOUBLE_BUF_NORMAL#define DOUBLE_BUF_DEBUG#define DOUBLE_BUF_ERROR#define DOUBLE_BUF_ASSERT#ifdef DOUBLE_BUF_NORMAL#define nprintf(fmt, args...)\do {\fprintf(stderr, fmt, ##args);\} while(0)#else#define nprintf(fmt, args...)NULL#endif#ifdef DOUBLE_BUF_DEBUG#define dprintf(fmt, args...)\do {\fprintf(stderr, "[D] "fmt, ##args);\} while(0)#else#define dprintf(fmt, args...)NULL#endif#ifdef DOUBLE_BUF_ERROR#define eprintf(fmt, args...)\do {\fprintf(stderr, "[E] "fmt, ##args);\} while(0)#else#define eprintf(fmt, args...)NULL#endif#ifdef DOUBLE_BUF_ASSERT#define dbassert(cond)\if(cond)\NULL;\else\fflush(stdout),\fflush(stderr),\fprintf(stderr, "Assertion failed: expr[%s], file[%s], func[%s], line[%u]\n",\#cond, __FILE__, __func__, __LINE__),\fflush(stderr),\abort()#else#definedbassert(cond)NULL#endiftypedef struct buf {void *pdata;int index;int status;int size;}buf_t;typedef struct double_buf {buf_t buf[2];pthread_mutex_t mutex;}double_buf_t;enum double_buf_status {WRITABLE = 0,READABLE,DEAD,};/** * @创建一个双缓冲区 * @db: 双缓冲结构体指针 * @size: 每个缓冲区的大小 * @return SUCC/FAIL */int create_double_buf(double_buf_t *db, int size);/** * @销毁一个双缓冲区 */void destroy_double_buf(double_buf_t *db);/** * @往双缓冲中写数据 * @db: 双缓冲结构体指针 * @wdata: 数据指针 * @size: 数据大小 * @return SUCC/FAIL */int write_double_buf(double_buf_t *db, void *wdata, int size);/** * @往双缓冲中写数据 * @db: 双缓冲结构体指针 * @wdata: 数据指针 * @size: 数据大小 * @return SUCC * @如果两个缓冲区都满了将覆盖第一个缓冲区 */int write_double_buf_cover(double_buf_t *db, void *wdata, int size);/** * @从双缓冲中读数据 * @db: 双缓冲结构体指针 * @rdata: 数据指针 * @size: 数据大小 * @return SUCC/FAIL */int read_double_buf(double_buf_t *db, void *rdata, int size);#ifdef __cplusplus}#endif#endif/* doublebuffer.h ending */
/* doublebuffer.c starting */#include "doublebuffer.h"#include <memory.h>static inline void __lock_double_buf(pthread_mutex_t *mutex){pthread_mutex_lock(mutex);}static inline void lock_double_buf(double_buf_t *db){__lock_double_buf(&db->mutex);}static inline void __unlock_double_buf(pthread_mutex_t *mutex){pthread_mutex_unlock(mutex);}static inline void unlock_double_buf(double_buf_t *db){__unlock_double_buf(&db->mutex);}/** * @找到一个可写缓冲区 * @return 缓冲区编号/FAIL */static int find_writable_buf(double_buf_t *db, int size){int i;for(i=0; i<2; i++){if(db->buf[i].status==WRITABLE   && (db->buf[i].index+size)<=db->buf[i].size)   return i;}return FAIL;}/** * @找到一个可读缓冲区 * @return 缓冲区编号/FAIL */static int find_readable_buf(double_buf_t *db, int size){int i;for(i=0; i<2; i++){if(db->buf[i].status==READABLE   && db->buf[i].index>=size)   return i;}return FAIL;}static void __write_double_buf(double_buf_t *db, int n, void *wdata, int size){int index = db->buf[n].index;memcpy(db->buf[n].pdata+index, wdata, size);db->buf[n].index += size;if(db->buf[n].index >= db->buf[n].size)db->buf[n].status = READABLE;}static int __read_double_buf(double_buf_t *db, int n, void *rdata, int size){static int rindex = 0;if(rindex + size > db->buf[n].size)return FAIL;memcpy(rdata, db->buf[n].pdata+rindex, size);rindex += size;if(rindex >= db->buf[n].size){rindex = 0;db->buf[n].index = 0;db->buf[n].status = WRITABLE;}return SUCC;}/** * @创建一个双缓冲区 * @db: 双缓冲结构体指针 * @size: 每个缓冲区的大小 * @return SUCC/FAIL */int create_double_buf(double_buf_t *db, int size){int i;dbassert(db);dbassert(size > 0);db->buf[0].pdata = (void *)malloc(size);if(!db->buf[0].pdata)return FAIL;db->buf[1].pdata = (void *)malloc(size);if(!db->buf[1].pdata){free(db->buf[0].pdata);return FAIL;}for(i=0; i<2; i++){db->buf[i].index = 0;db->buf[i].status = WRITABLE;db->buf[i].size = size;}pthread_mutex_init(&db->mutex, NULL);return SUCC;}/** * @销毁一个双缓冲区 */void destroy_double_buf(double_buf_t *db){int i;dbassert(db);lock_double_buf(db);for(i=0; i<2; i++){free(db->buf[i].pdata);db->buf[i].status = DEAD;db->buf[i].index = 0;}unlock_double_buf(db);}/** * @往双缓冲中写数据 * @db: 双缓冲结构体指针 * @wdata: 数据指针 * @size: 数据大小 * @return SUCC/FAIL */int write_double_buf(double_buf_t *db, void *wdata, int size){int i;dbassert(db);dbassert(wdata);dbassert(size);lock_double_buf(db);i = find_writable_buf(db, size);if(i < 0){unlock_double_buf(db);return FAIL;}__write_double_buf(db, i, wdata, size);unlock_double_buf(db);return SUCC;}/** * @往双缓冲中写数据 * @db: 双缓冲结构体指针 * @wdata: 数据指针 * @size: 数据大小 * @return SUCC * @如果两个缓冲区都满了将覆盖第一个缓冲区 */int write_double_buf_cover(double_buf_t *db, void *wdata, int size){int i;dbassert(db);dbassert(wdata);dbassert(size);lock_double_buf(db);i = find_writable_buf(db, size);if(i < 0){i = 0;db->buf[i].status = WRITABLE;db->buf[i].index = 0;}__write_double_buf(db, i, wdata, size);unlock_double_buf(db);return SUCC;}/** * @从双缓冲中读数据 * @db: 双缓冲结构体指针 * @rdata: 数据指针 * @size: 数据大小 * @return SUCC/FAIL */int read_double_buf(double_buf_t *db, void *rdata, int size){int i;dbassert(db);dbassert(rdata);dbassert(size);lock_double_buf(db);i = find_readable_buf(db, size);if(i < 0){unlock_double_buf(db);return FAIL;}i = __read_double_buf(db, i, rdata, size);if(i < 0){unlock_double_buf(db);return FAIL;}unlock_double_buf(db);return SUCC;}/* doublebuffer.c ending */
0 0