From c1b4872b0910c9aa784d878dca771b21c4690048 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 22:53:09 +0000 Subject: lots of work git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@30 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- bufferq.c | 147 +++++++++++++++++++++++++++----------------------------------- 1 file changed, 63 insertions(+), 84 deletions(-) (limited to 'bufferq.c') diff --git a/bufferq.c b/bufferq.c index 5261f35..1965dda 100644 --- a/bufferq.c +++ b/bufferq.c @@ -4,7 +4,7 @@ #include "macro.h" #include "bufferq.h" -#define SA_BUFFERQ_CONCAT_DATA(x) ((void*) (uint8_t*) (x) + ALIGN(sizeof(sa_bufferq_item_t))) +#define SA_BUFFERQ_ITEM_CONCAT_DATA(x) ((void*) (uint8_t*) (x) + SA_ALIGN(sizeof(sa_bufferq_item_t))) int sa_bufferq_init(sa_bufferq_t *q, unsigned nchannels, size_t sample_size) { sa_assert(q); @@ -44,23 +44,30 @@ void sa_bufferq_done(sa_bufferq_t *q) { sa_free(q->last); } -static sa_bufferq_item_t* bufferq_item_new(const void *d, size_t size, int copy) { +static sa_bufferq_item_t* bufferq_item_new(const void *d, int64_t idx, size_t size, sa_bufferq_item_type_t type) { sa_bufferq_item_t *i; sa_assert(size > 0); - if (!copy) { + if (type == SA_BUFFERQ_ITEM_STATIC) { if (!(i = sa_new(sa_bufferq_item_t, 1))) - return i; - i->type = SA_BUFFERQ_ITEM_STATIC; + return NULL; i->data = (void*) d; - } else { - if (!(i = sa_malloc(ALIGN(sizeof(sa_bufferq_item_t)) + size))) - return i; - i->type = SA_BUFFERQ_ITEM_CONCATENATED; - i->data = SA_BUFFERQ_CONCAT_DATA(i); + } else if (type == SA_BUFFERQ_ITEM_CONCATENATED) { + if (!(i = sa_malloc(SA_ALIGN(sizeof(sa_bufferq_item_t)) + size))) + return NULL; + i->data = SA_BUFFERQ_ITEM_CONCAT_DATA(i); memcpy(i->data, d, size); + } else { + sa_assert(type == SA_BUFFERQ_ITEM_DYNAMIC); + + if (!(i = sa_new(sa_bufferq_item_t, 1))) + return NULL; + + i->data = (void*) d; } + i->type = type; + i->idx = idx; i->size = size; SA_LLIST_ITEM_INIT(sa_bufferq_item_t, bufferq, i); @@ -90,9 +97,9 @@ static void bufferq_item_free(sa_bufferq_item_t *i) { sa_free(i); } -int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence, int copy) { +int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence, sa_bufferq_item_type_t type) { int64_t idx; - sa_bufferq_item_t *i, *j; + sa_bufferq_item_t *i, *j, *n; sa_assert(q); @@ -110,7 +117,7 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t sa_assert_not_reached(); } - if (q->read_index > idx) { + if (q->read_index > idx && type != SA_BUFFERQ_ITEM_DYNAMIC) { int64_t l = q->read_index - idx; if (l > nbytes) @@ -122,72 +129,39 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t } - i = q->items[channel]; - - while (i && nbytes > 0) { - - if (idx >= i->idx + i->size) { - /* The new data belongs behind the current node */ - - i = i->bufferq_next; - - } else if (idx < i->idx) { - size_t l; - /* The new data belongs before the current node (at least partially) */ - - l = nbytes; - - if (l > i->idx - idx) - l = i->idx - idx; - - if (!(j = bufferq_item_new(data, l, copy))) - return SA_ERROR_OOM; - - j->idx = idx; - - SA_LLIST_INSERT_BEFORE(sa_bufferq_item_t, bufferq, q->items[channel], i, j); - - idx += l; - data += l; - nbytes -= l; - - } else { - size_t l; - - /* The data belongs right in the current node somewhere */ - - l = nbytes; + /* Allocate the new entry */ + if (!(j = bufferq_item_new(data, idx, nbytes, type))) + return SA_ERROR_OOM; - if (l > i->idx + i->size - idx) - l = i->idx + i->size - idx; + /* Find the position where we need to insert the new entry */ + for (i = q->items[channel]; i && idx >= i->idx + i->size; i = i->bufferq_next) + ; - if (!(i = bufferq_item_make_writable(i))) - return SA_ERROR_OOM; - - memcpy((uint8_t*) i->data + (idx - i->idx), data, l); - - idx += l; - data += l; - nbytes -= l; - } + /* Shorten the current entry if necessary */ + if (i && idx > i->idx) { + i->size = idx - i->idx; + i = i->bufferq_next; } - - if (nbytes > 0) { - sa_assert(!i); - - if (!(j = bufferq_item_new(data, nbytes, copy))) - return SA_ERROR_OOM; - - j->idx = idx; - + + /* Insert the entry */ + if (i) + SA_LLIST_INSERT_BEFORE(sa_bufferq_item_t, bufferq, q->items[channel], i, j); + else { if (q->last[channel]) SA_LLIST_INSERT_AFTER(sa_bufferq_item_t, bufferq, q->items[channel], q->last[channel], j); else SA_LLIST_PREPEND(sa_bufferq_item_t, bufferq, q->items[channel], j); - + q->last[channel] = j; } - + + /* Now kick all the entries that overlap entirely with our new entry */ + for (i = j->bufferq_next; i && i->idx + i->size < j->idx + j->size ; i = n) { + n = i->bufferq_next; + SA_LLIST_REMOVE(sa_bufferq_item_t, bufferq, q->items[channel], i); + bufferq_item_free(i); + } + q->write_index = idx + nbytes; if (q->write_index > q->end_index) @@ -196,7 +170,7 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t return SA_SUCCESS; } -int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) { +void sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) { int first = 1; unsigned u; sa_assert(q); @@ -221,7 +195,7 @@ int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) { } else { int64_t l; - i[u] = (uint8_t*) q->items[u]->data + q->read_index - q->items[u]->idx; + i[u] = (uint8_t*) q->items[u]->data + q->read_index - q->items[u]->idx; l = q->items[u]->size - (q->read_index - q->items[u]->idx); @@ -235,12 +209,10 @@ int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) { } else i[u] = NULL; } - - return SA_SUCCESS; } -int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) { +void sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) { unsigned u; sa_assert(q); @@ -264,28 +236,35 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) { if (!i) q->last[u] = NULL; } - - return SA_SUCCESS; } int sa_bufferq_realloc(sa_bufferq_t *q) { unsigned u; + int fail = 0; sa_assert(q); for (u = 0; u < q->nchannels; u++) { sa_bufferq_item_t *i; - i = q->items[u]; + for (i = q->items[u]; i; i = i->bufferq_next) { - while (i) { + if (i->type != SA_BUFFERQ_ITEM_STATIC) + continue; - if (!bufferq_item_make_writable(i)) - return SA_ERROR_OOM; + if (!bufferq_item_make_writable(i)) { + fail = 1; - i = i->bufferq_next; + /* Hmm, we couldn't allocate memory, but we can't + * return without doing anything, hence let's at least + * drop the reference to the statically allocated + * data */ + + i->size = 0; + i->data = SA_BUFFERQ_ITEM_CONCAT_DATA(i); + i->type = SA_BUFFERQ_ITEM_CONCATENATED; + } } - } - return SA_SUCCESS; + return fail ? SA_ERROR_OOM : SA_SUCCESS; } -- cgit