1、实现代码
#include "sbuf.h"
#include "csapp.h"
typedef struct{
int *buf;
int n;
int front;
int rear;
sem_t mutex;
sem_t solts;
sem_t items;
}sbuf_t;
//初始化,分配内存,初始化信号
void sbuf_init(sbuf_t *sp,int n)
{
sp->buf = Calloc(n,sizeof(int));
sp->n = n;
sp->front = sp->rear = 0;
Sem_init(&sp->mutex,0,1);
Sem_init(&sp->slots,0,n);
Sem_init(&sp->items,0,0);
}
//释放缓冲区
void sbuf_deinit(sbuf_t *sp)
{
Free(sp->buf);
}
//添加项目
void sbuf_insert(sbuf_t *sp,int item)
{
P(&sp->slots);
P(&sp->mutex);
sp->buf[(++sp->rear)%(sp->n)]=item;
V(&sp->mutex);
V(&sp->items);
}
//取出项目
void sbuf_remove(sbuf_t *sp)
{
int item;
P(&sp->item);
P(&sp->mutex);
item = sp->buf[(++sp->front)%(sp->n)];
V(&sp->mutex);
V(&sp->slots);
return item;
}
2、代码分析
SBUF操作类型为sbuf_t的有限缓冲区,项目存放在一个动态分配的n项整数数组中,front和rear索引值记录该数组的第一项和最后一项,三个信号量同步对缓冲区的访问,mutex信号量提供互斥的缓冲区的访问,slots和items信号量分贝纪录空槽位和可用项目的数量。
sbuf_init函数为缓冲区分配堆内存,设置front和rear表示一个空的缓冲区,并为三个信号量赋初值,这个函数在调用其他三个函数中任何一个之前调用一次,sbuf_deinit函数是当应用程序使用完缓冲区时,释放缓冲区存储的。sbuf_insert函数等待一个可用的槽位,对互斥锁加锁,添加项目,对互斥锁解锁,然后宣布有一个新的项目可用。sbuf_remove函数与sbuf_insert函数对称,等待一个可用的缓冲区项目之后,对互斥锁加锁,从缓冲区的前面取出该项目,对互斥锁解锁,然后发信号通知一个新的槽位可供使用。