www.pudn.com > streamrtp.rar > bufpool.c


/*-------------------------------------------------------------------------
 * bufpool.c - bufpoolinit, bufpoolgetbuf, bufpoolfreebuf, bufpooldestroy
 *
 * Bufferpool design is adapted from:
 * 
 * Comer, D. E., Operating System Design: The XINU Approach, Prentice-Hall,
 * 1984.
 *-------------------------------------------------------------------------
 */

#include 
#include 
#include 

/*------------------------------------------------------------------------
 * bufpoolinit - allocate memory for a pool of fixed-size buffers
 * and link together
 *------------------------------------------------------------------------
 */
int
bufpoolinit(struct bufpool *pbp, int bufsize, int numbufs)
{

	char *where;

	if (bufsize < BPMINB)
		return ERROR;
  
	where = pbp->bp_base = (char *) malloc((bufsize + sizeof(struct bufpool *)) * numbufs);
	if (where == NULL)
		return ERROR;

	pbp->bp_total = numbufs;
	pbp->bp_next = where;
	pbp->bp_size = bufsize;
	sem_init(&pbp->bp_sem, FALSE, numbufs);
	pthread_mutex_init(&pbp->bp_mutex, NULL);

	bufsize += sizeof(struct bufpool *);

	for (numbufs-- ; numbufs > 0 ; numbufs--, where += bufsize)
		*((int *) where ) = (int) (where + bufsize);
	*((int *) where) = (int) NULL;

	return OK;
}


/*------------------------------------------------------------------------
 * bufpoolgetbuf - get a fixed size buffer
 *------------------------------------------------------------------------
 */
int *
bufpoolgetbuf(struct bufpool *pbp)
{

	int	*buf;

	if (sem_trywait(&pbp->bp_sem) != 0)
		return NULL;
  
	if (pthread_mutex_lock(&pbp->bp_mutex) != 0) {
		sem_post(&pbp->bp_sem);
		return NULL;
	}
  
	buf = (int *) pbp->bp_next;
	pbp->bp_next = (char *) *buf;
	pthread_mutex_unlock(&pbp->bp_mutex);
  
	*buf = (int) pbp;
	return buf + 1;
}

/*------------------------------------------------------------------------
 *  bufpoolfreebuf - free a buffer that was allocated from a pool by getbuf
 *------------------------------------------------------------------------
 */
void
bufpoolfreebuf(void *vbuf)
{
  
	int			*buf = (int *) vbuf;
	struct bufpool	*pbp;

	pbp = (struct bufpool *) *(--buf);

	pthread_mutex_lock(&pbp->bp_mutex);
  
	*buf = (int) pbp->bp_next;
	pbp->bp_next = (char *) buf;
  
	pthread_mutex_unlock(&pbp->bp_mutex);
	sem_post(&pbp->bp_sem);
}

/*------------------------------------------------------------------------
 *  bufpooldestroy - destroy a pool of buffers
 *------------------------------------------------------------------------
 */
int
bufpooldestroy(struct bufpool *pbp)
{
  
	int i;
  
	if (pbp == NULL)
		return ERROR;

	for (i = 0; i < pbp->bp_total; i++)
		sem_wait(&pbp->bp_sem);

	free(pbp->bp_base);
	sem_destroy(&pbp->bp_sem);
	pthread_mutex_destroy(&pbp->bp_mutex);

	return OK;
}