|
|
|
@ -25,6 +25,7 @@ struct bpool_shard {
|
|
|
|
|
void *end;
|
|
|
|
|
void *head;
|
|
|
|
|
bool full;
|
|
|
|
|
shard_list link;
|
|
|
|
|
unsigned int (*recycle)(void *);
|
|
|
|
|
void *arg;
|
|
|
|
|
};
|
|
|
|
@ -49,9 +50,8 @@ static void bufferpool_recycle(struct bpool_shard *shard) {
|
|
|
|
|
|
|
|
|
|
if (shard->refs == 0) {
|
|
|
|
|
shard->full = false;
|
|
|
|
|
shard_list *link = t_queue_find(&bp->full_shards, shard); // XXX avoid this
|
|
|
|
|
t_queue_delete_link(&bp->full_shards, link);
|
|
|
|
|
t_queue_push_tail(&bp->empty_shards, shard);
|
|
|
|
|
t_queue_unlink(&bp->full_shards, &shard->link);
|
|
|
|
|
t_queue_push_tail_link(&bp->empty_shards, &shard->link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -80,6 +80,7 @@ static struct bpool_shard *bufferpool_new_shard(struct bufferpool *bp) {
|
|
|
|
|
ret->bp = bp;
|
|
|
|
|
ret->buf = buf;
|
|
|
|
|
ret->end = buf + BUFFERPOOL_SHARD_SIZE;
|
|
|
|
|
ret->link.data = ret;
|
|
|
|
|
|
|
|
|
|
struct bpool_shard **head = buf;
|
|
|
|
|
*head = ret;
|
|
|
|
@ -107,15 +108,15 @@ void *bufferpool_alloc(struct bufferpool *bp, size_t len) {
|
|
|
|
|
while (true) {
|
|
|
|
|
if (!bp->empty_shards.length) {
|
|
|
|
|
shard = bufferpool_new_shard(bp);
|
|
|
|
|
t_queue_push_tail(&bp->empty_shards, shard);
|
|
|
|
|
t_queue_push_tail_link(&bp->empty_shards, &shard->link);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
shard = bp->empty_shards.head->data;
|
|
|
|
|
if (shard->head + len <= shard->end)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
t_queue_pop_head(&bp->empty_shards);
|
|
|
|
|
t_queue_push_tail(&bp->full_shards, shard);
|
|
|
|
|
t_queue_unlink(&bp->empty_shards, &shard->link);
|
|
|
|
|
t_queue_push_tail_link(&bp->full_shards, &shard->link);
|
|
|
|
|
|
|
|
|
|
shard->full = true;
|
|
|
|
|
shard_check_full(shard);
|
|
|
|
@ -136,14 +137,14 @@ void *bufferpool_reserve(struct bufferpool *bp, unsigned int refs, unsigned int
|
|
|
|
|
|
|
|
|
|
struct bpool_shard *shard = t_queue_peek_head(&bp->empty_shards);
|
|
|
|
|
if (shard && shard->head == shard->empty && shard->refs == 0)
|
|
|
|
|
t_queue_pop_head(&bp->empty_shards);
|
|
|
|
|
t_queue_unlink(&bp->empty_shards, &shard->link);
|
|
|
|
|
else
|
|
|
|
|
shard = bufferpool_new_shard(bp);
|
|
|
|
|
|
|
|
|
|
// set references, set recycle callback, move to full list
|
|
|
|
|
shard->refs = refs;
|
|
|
|
|
shard->full = true;
|
|
|
|
|
t_queue_push_tail(&bp->full_shards, shard);
|
|
|
|
|
t_queue_push_tail_link(&bp->full_shards, &shard->link);
|
|
|
|
|
shard->recycle = recycle;
|
|
|
|
|
shard->arg = arg;
|
|
|
|
|
|
|
|
|
@ -163,11 +164,11 @@ static void bpool_shard_destroy(struct bpool_shard *shard) {
|
|
|
|
|
static void bpool_shard_delayed_destroy(struct bufferpool *bp, struct bpool_shard *shard) {
|
|
|
|
|
if (shard->full) {
|
|
|
|
|
shard_list *link = t_queue_find(&bp->full_shards, shard);
|
|
|
|
|
t_queue_delete_link(&bp->full_shards, link);
|
|
|
|
|
t_queue_unlink(&bp->full_shards, link);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
shard_list *link = t_queue_find(&bp->empty_shards, shard);
|
|
|
|
|
t_queue_delete_link(&bp->empty_shards, link);
|
|
|
|
|
t_queue_unlink(&bp->empty_shards, link);
|
|
|
|
|
}
|
|
|
|
|
bpool_shard_destroy(shard);
|
|
|
|
|
}
|
|
|
|
@ -232,8 +233,8 @@ static void bpool_destroy_shards(shard_q *q) {
|
|
|
|
|
shard_list *n = l->next;
|
|
|
|
|
struct bpool_shard *shard = l->data;
|
|
|
|
|
if (shard->refs == 0) {
|
|
|
|
|
t_queue_unlink(q, l);
|
|
|
|
|
bpool_shard_destroy(shard);
|
|
|
|
|
t_queue_delete_link(q, l);
|
|
|
|
|
}
|
|
|
|
|
l = n;
|
|
|
|
|
}
|
|
|
|
|