#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; }