101 lines
2.2 KiB
C
101 lines
2.2 KiB
C
|
#include "mpool.h"
|
|||
|
|
|||
|
/*
|
|||
|
* инициализация пула
|
|||
|
*/
|
|||
|
void mpool_init(struct mpool_s *bp, size_t nblocks, size_t mpool_block_size)
|
|||
|
{
|
|||
|
size_t i;
|
|||
|
|
|||
|
bp->nblocks = nblocks;
|
|||
|
|
|||
|
mpool_block_size += 2 * sizeof(struct mpool_block_s *);
|
|||
|
|
|||
|
bp->pool = (struct mpool_block_s *)malloc(nblocks * mpool_block_size);
|
|||
|
|
|||
|
if (!bp->pool)
|
|||
|
fatal("virtual memory exhaused");
|
|||
|
|
|||
|
void *p = bp->pool + mpool_block_size,
|
|||
|
*pmax = p + (nblocks - 2) * mpool_block_size;
|
|||
|
|
|||
|
for ( ; p < pmax; p += mpool_block_size) {
|
|||
|
((struct mpool_block_s *)p)->prev = (struct mpool_block_s *)(p - mpool_block_size);
|
|||
|
((struct mpool_block_s *)p)->next = (struct mpool_block_s *)(p + mpool_block_size);
|
|||
|
}
|
|||
|
|
|||
|
((struct mpool_block_s *)bp->pool)->prev = NULL;
|
|||
|
((struct mpool_block_s *)bp->pool)->next = (struct mpool_block_s *)(bp->pool + mpool_block_size);
|
|||
|
|
|||
|
((struct mpool_block_s *)(bp->pool + (nblocks - 1) * mpool_block_size))->prev =
|
|||
|
(struct mpool_block_s *)(bp->pool + (nblocks - 2) * mpool_block_size);
|
|||
|
((struct mpool_block_s *)(bp->pool + (nblocks - 1) * mpool_block_size))->next = NULL;
|
|||
|
|
|||
|
bp->free_pool = (struct mpool_block_s *)bp->pool;
|
|||
|
bp->busy_pool = NULL;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* уничтожение пула
|
|||
|
*/
|
|||
|
void mpool_destroy(struct mpool_s *bp)
|
|||
|
{
|
|||
|
free(bp->pool);
|
|||
|
bp->nblocks = 0;
|
|||
|
bp->pool = bp->free_pool = bp->busy_pool = NULL;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* выдача блока из пула
|
|||
|
*/
|
|||
|
void *mpool_alloc(struct mpool_s *bp)
|
|||
|
{
|
|||
|
if (!bp->free_pool)
|
|||
|
return NULL;
|
|||
|
|
|||
|
bp->free_pool->prev = bp->free_pool->next; // save free_pool->next in free_pool->prev
|
|||
|
|
|||
|
bp->free_pool->next = bp->busy_pool;
|
|||
|
|
|||
|
if (bp->busy_pool)
|
|||
|
bp->busy_pool->prev = bp->free_pool;
|
|||
|
|
|||
|
bp->busy_pool = bp->free_pool;
|
|||
|
|
|||
|
bp->free_pool = bp->free_pool->prev;
|
|||
|
|
|||
|
bp->busy_pool->prev = NULL; // saved in free_pool->prev to NULL
|
|||
|
|
|||
|
return &bp->busy_pool->obj;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* возвращение блока в пул
|
|||
|
*/
|
|||
|
void mpool_free(struct mpool_s *bp, void *p)
|
|||
|
{
|
|||
|
if (!p)
|
|||
|
return;
|
|||
|
|
|||
|
struct mpool_block_s *b1 = (struct mpool_block_s *)(p - 2 * sizeof(struct mpool_block_s *)),
|
|||
|
*b2 = b1->next;
|
|||
|
|
|||
|
if (b1->prev)
|
|||
|
b1->prev->next = b2;
|
|||
|
if (b2)
|
|||
|
b2->prev = b1->prev;
|
|||
|
|
|||
|
if (bp->free_pool) {
|
|||
|
b1->next = bp->free_pool;
|
|||
|
bp->free_pool->prev = b1;
|
|||
|
}
|
|||
|
else
|
|||
|
b1->next = NULL;
|
|||
|
|
|||
|
bp->free_pool = b2;
|
|||
|
|
|||
|
if (bp->busy_pool == b1)
|
|||
|
bp->busy_pool = b2;
|
|||
|
}
|
|||
|
|