diff options
author | Lennart Poettering <lennart@poettering.net> | 2004-06-08 23:54:24 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2004-06-08 23:54:24 +0000 |
commit | 9cb0b933e260008c6a03e24a4a149f726b8d86b2 (patch) | |
tree | b54651bafe32d1a817e779f884d1628176465bf0 /src/memblockq.c | |
parent | b1c00dcd0ae51d201f772e7f5fa61acae436a2cf (diff) |
initial commit
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@3 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/memblockq.c')
-rw-r--r-- | src/memblockq.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/memblockq.c b/src/memblockq.c new file mode 100644 index 00000000..1424c556 --- /dev/null +++ b/src/memblockq.c @@ -0,0 +1,156 @@ +#include <assert.h> +#include <stdlib.h> + +#include "memblockq.h" + +struct memblock_list { + struct memblock_list *next; + struct memchunk chunk; +}; + +struct memblockq { + struct memblock_list *blocks, *blocks_tail; + unsigned n_blocks; + size_t total_length; + size_t maxlength; + size_t base; +}; + +struct memblockq* memblockq_new(size_t maxlength, size_t base) { + struct memblockq* bq; + assert(maxlength && base); + + bq = malloc(sizeof(struct memblockq)); + assert(bq); + bq->blocks = bq->blocks_tail = 0; + bq->n_blocks = 0; + bq->total_length = 0; + bq->base = base; + bq->maxlength = ((maxlength+base-1)/base)*base; + assert(bq->maxlength >= base); + return bq; +} + +void memblockq_free(struct memblockq* bq) { + struct memblock_list *l; + assert(bq); + + while ((l = bq->blocks)) { + bq->blocks = l->next; + memblock_unref(l->chunk.memblock); + free(l); + } + + free(bq); +} + +void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) { + struct memblock_list *q; + assert(bq && chunk && chunk->memblock && chunk->index); + + q = malloc(sizeof(struct memblock_list)); + assert(q); + + q->chunk = *chunk; + memblock_ref(q->chunk.memblock); + assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); + q->next = NULL; + + if (bq->blocks_tail) + bq->blocks_tail->next = q; + else + bq->blocks = q; + + bq->blocks_tail = q; + + bq->n_blocks++; + bq->total_length += chunk->length; + + memblockq_shorten(bq, bq->maxlength); +} + +int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { + assert(bq && chunk); + + if (!bq->blocks) + return -1; + + *chunk = bq->blocks->chunk; + memblock_ref(chunk->memblock); + return 0; +} + +int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { + struct memblock_list *q; + + assert(bq && chunk); + + if (!bq->blocks) + return -1; + + q = bq->blocks; + bq->blocks = bq->blocks->next; + + *chunk = q->chunk; + + bq->n_blocks--; + bq->total_length -= chunk->length; + + free(q); + return 0; +} + +void memblockq_drop(struct memblockq *bq, size_t length) { + assert(bq); + + while (length > 0) { + size_t l = length; + assert(bq->blocks && bq->total_length >= length); + + if (l > bq->blocks->chunk.length) + l = bq->blocks->chunk.length; + + bq->blocks->chunk.index += l; + bq->blocks->chunk.length -= l; + bq->total_length -= l; + + if (bq->blocks->chunk.length == 0) { + struct memblock_list *q; + + q = bq->blocks; + bq->blocks = bq->blocks->next; + memblock_unref(q->chunk.memblock); + free(q); + + bq->n_blocks--; + } + + length -= l; + } +} + +void memblockq_shorten(struct memblockq *bq, size_t length) { + size_t l; + assert(bq); + + if (bq->total_length <= length) + return; + + l = bq->total_length - length; + l /= bq->base; + l *= bq->base; + + memblockq_drop(bq, l); +} + + +void memblockq_empty(struct memblockq *bq) { + assert(bq); + memblockq_shorten(bq, 0); +} + +int memblockq_is_empty(struct memblockq *bq) { + assert(bq); + + return bq->total_length >= bq->base; +} |